From 045f7fa401c2a5b62a2f5cb94c1e489f0affb99e Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 23 Oct 2010 15:58:19 +1100 Subject: [PATCH 01/82] wrap copier.c in an ifdef so arduino ide doesn't try to include it --- copier.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/copier.c b/copier.c index 23ca0cd..9317d9a 100644 --- a/copier.c +++ b/copier.c @@ -1,11 +1,12 @@ +#ifdef COPIER + #include "copier.h" #include #include #include "arduino.h" -#include "timer.h" -#include "serial.h" +#include "delay.h" uint32_t copier_xchange(uint32_t cmd) { uint32_t r = 0, c = cmd; @@ -96,3 +97,5 @@ void copy() { SET_INPUT(SCK); SET_INPUT(COPIER_RESET); } + +#endif /* COPIER */ From efda8ed7ce46f2c308cca9fdffbc019e3ab3554f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 23 Oct 2010 16:02:51 +1100 Subject: [PATCH 02/82] add license, and mention in Makefile and README --- LICENSE | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 17 +++ README | 28 ++++- 3 files changed, 383 insertions(+), 2 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile index 197697b..9a265af 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,23 @@ # # # by Triffid Hunter, Traumflug, jakepoz # # # +# # +# This firmware is Copyright (C) 2009-2010 Michael Moon aka Triffid_Hunter # +# # +# This program 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 2 of the License, or # +# (at your option) any later version. # +# # +# This program 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 this program; if not, write to the Free Software # +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # +# # ############################################################################## ############################################################################## diff --git a/README b/README index 3b5557c..5056a03 100644 --- a/README +++ b/README @@ -2,8 +2,10 @@ Rewrite of Reprap Mendel firmware: * 100% integer computations * serial transmit buffer -* can fit onto atmega168 -* fits onto atmega328p etc +* can fit onto atmega168 depending on selected options +* works on atmega328p +* works on atmega644p +* porting to atmega1280 in progress * will work on larger atmegas with minor porting ############################################################################## @@ -20,6 +22,28 @@ Rewrite of Reprap Mendel firmware: 6) have a play, go to 1) if not right 7) try printing something! +############################################################################## +# # +# License # +# # +############################################################################## + +This firmware is Copyright (C) 2009-2010 Michael Moon aka Triffid_Hunter + +This program 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 2 of the License, or +(at your option) any later version. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ############################################################################## # # # Rationale and History # From f93161cba1732ea89a2d13e1d3b11dac99f26aaf Mon Sep 17 00:00:00 2001 From: Markus Hitter Date: Mon, 25 Oct 2010 11:44:05 +0200 Subject: [PATCH 03/82] Makefile: add other configuration values in comments. --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 9a265af..c5014c3 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,10 @@ SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dd # # ############################################################################## +#MCU_TARGET = atmega168 MCU_TARGET = atmega328p +#MCU_TARGET = atmega644p +#MCU_TARGET = atmega1280 F_CPU = 16000000L ############################################################################## @@ -88,6 +91,9 @@ AVRDUDECONF = /etc/avrdude.conf # # ############################################################################## PROGPORT = /dev/arduino +# atmega168 +#PROGBAUD = 19200 +# atmega328p, 644p, 1280 PROGBAUD = 57600 OBJ = $(patsubst %.c,%.o,${SOURCES}) From cf285b4559ad8fa821a1dc23dbc80680a5946c48 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 18 Oct 2010 18:14:14 +1100 Subject: [PATCH 04/82] split gcode parse/process into separate files for readability --- Makefile | 2 +- gcode.c => gcode_parse.c | 412 ++------------------------------------- gcode.h => gcode_parse.h | 11 +- gcode_process.c | 393 +++++++++++++++++++++++++++++++++++++ gcode_process.h | 9 + mendel.c | 4 +- 6 files changed, 422 insertions(+), 409 deletions(-) rename gcode.c => gcode_parse.c (53%) rename gcode.h => gcode_parse.h (91%) create mode 100644 gcode_process.c create mode 100644 gcode_process.h diff --git a/Makefile b/Makefile index c5014c3..f28534d 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode.c timer.c clock.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c clock.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c ############################################################################## # # diff --git a/gcode.c b/gcode_parse.c similarity index 53% rename from gcode.c rename to gcode_parse.c index 50a3ae1..dd6ace8 100644 --- a/gcode.c +++ b/gcode_parse.c @@ -1,20 +1,14 @@ -#include "gcode.h" +#include "gcode_parse.h" #include -#include "config.h" #include "serial.h" #include "sermsg.h" -#include "temp.h" -#include "timer.h" #include "dda_queue.h" -#include "dda.h" -#include "clock.h" -#include "watchdog.h" #include "debug.h" #include "heater.h" -#include "sersendf.h" -#include "delay.h" + +#include "gcode_process.h" /* Switch user friendly values to coding friendly values @@ -124,7 +118,7 @@ void SpecialMoveE(int32_t e, uint32_t f) { * * ****************************************************************************/ -void scan_char(uint8_t c) { +void gcode_parse_char(uint8_t c) { #ifdef ASTERISK_IN_CHECKSUM_INCLUDED if (next_target.seen_checksum == 0) next_target.checksum_calculated = crc(next_target.checksum_calculated, c); @@ -245,6 +239,7 @@ void scan_char(uint8_t c) { // process character switch (c) { // each currently known command is either G or M, so preserve previous G/M unless a new one has appeared + // FIXME: same for T command case 'G': next_target.seen_G = 1; next_target.seen_M = 0; @@ -294,7 +289,7 @@ void scan_char(uint8_t c) { // now for some numeracy case '-': read_digit.sign = 1; - // force sign to be at start of number + // force sign to be at start of number, so 1-2 = -2 instead of -12 read_digit.exponent = 0; read_digit.mantissa = 0; break; @@ -343,11 +338,11 @@ void scan_char(uint8_t c) { serial_writechar(c); if ( - #ifdef REQUIRE_LINENUMBER - ((next_target.N >= next_target.N_expected) && (next_target.seen_N == 1)) - #else + #ifdef REQUIRE_LINENUMBER + (next_target.N >= next_target.N_expected) && (next_target.seen_N == 1) + #else 1 - #endif + #endif ) { if ( #ifdef REQUIRE_CHECKSUM @@ -357,7 +352,7 @@ void scan_char(uint8_t c) { #endif ) { // process - process_gcode_command(&next_target); + process_gcode_command(); serial_writestr_P(PSTR("ok\n")); // expect next line number @@ -387,9 +382,11 @@ void scan_char(uint8_t c) { next_target.checksum_calculated = 0; last_field = 0; read_digit.sign = read_digit.mantissa = read_digit.exponent = 0; + // assume a G1 by default next_target.seen_G = 1; next_target.G = 1; + if (next_target.option_relative) { next_target.target.X = next_target.target.Y = next_target.target.Z = 0; next_target.target.E = 0; @@ -397,384 +394,6 @@ void scan_char(uint8_t c) { } } -/**************************************************************************** -* * -* Command Received - process it * -* * -****************************************************************************/ - -void process_gcode_command(GCODE_COMMAND *gcmd) { - uint32_t backup_f; - - // convert relative to absolute - if (gcmd->option_relative) { - gcmd->target.X += startpoint.X; - gcmd->target.Y += startpoint.Y; - gcmd->target.Z += startpoint.Z; - } - // E ALWAYS relative, otherwise we overflow our registers after only a few layers -// gcmd->target.E += startpoint.E; - // easier way to do this -// startpoint.E = 0; - // moved to dda.c, end of dda_create() and dda_queue.c, next_move() - - if (gcmd->seen_G) { - switch (gcmd->G) { - // G0 - rapid, unsynchronised motion - // since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects - case 0: - backup_f = gcmd->target.F; - gcmd->target.F = MAXIMUM_FEEDRATE_X * 2; - enqueue(&gcmd->target); - gcmd->target.F = backup_f; - break; - - // G1 - synchronised motion - case 1: - enqueue(&gcmd->target); - break; - - // G2 - Arc Clockwise - // unimplemented - - // G3 - Arc Counter-clockwise - // unimplemented - - // G4 - Dwell - case 4: - // wait for all moves to complete - for (;queue_empty() == 0;) - wd_reset(); - // delay - delay_ms(gcmd->P); - break; - - // G20 - inches as units - case 20: - gcmd->option_inches = 1; - break; - - // G21 - mm as units - case 21: - gcmd->option_inches = 0; - break; - - // G30 - go home via point - case 30: - enqueue(&gcmd->target); - // no break here, G30 is move and then go home - - // G28 - go home - case 28: - /* - Home XY first - */ - // hit endstops, no acceleration- we don't care about skipped steps - startpoint.F = MAXIMUM_FEEDRATE_X; - SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, MAXIMUM_FEEDRATE_X); - startpoint.X = startpoint.Y = 0; - - // move forward a bit - SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); - - // move back in to endstops slowly - SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); - - // wait for queue to complete - for (;queue_empty() == 0;) - wd_reset(); - - // this is our home point - startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0; - - /* - Home Z - */ - // hit endstop, no acceleration- we don't care about skipped steps - startpoint.F = MAXIMUM_FEEDRATE_Z; - SpecialMoveZ(-250L * STEPS_PER_MM_Z, MAXIMUM_FEEDRATE_Z); - startpoint.Z = 0; - - // move forward a bit - SpecialMoveZ(5 * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); - - // move back into endstop slowly - SpecialMoveZ(-20L * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); - - // wait for queue to complete - for (;queue_empty() == 0;) - wd_reset(); - - // this is our home point - startpoint.Z = current_position.Z = 0; - - /* - Home E - */ - // extruder only runs one way and we have no "endstop", just set this point as home - startpoint.E = current_position.E = 0; - - /* - Home F - */ - - // F has been left at SEARCH_FEEDRATE_Z by the last move, this is a usable "home" - // uncomment the following or substitute if you prefer a different default feedrate - // startpoint.F = SEARCH_FEEDRATE_Z - - break; - - // G90 - absolute positioning - case 90: - gcmd->option_relative = 0; - break; - - // G91 - relative positioning - case 91: - gcmd->option_relative = 1; - break; - - // G92 - set home - case 92: - startpoint.X = startpoint.Y = startpoint.Z = startpoint.E = - current_position.X = current_position.Y = current_position.Z = current_position.E = 0; - startpoint.F = - current_position.F = SEARCH_FEEDRATE_Z; - break; - - // unknown gcode: spit an error - default: - serial_writestr_P(PSTR("E: Bad G-code ")); - serwrite_uint8(gcmd->G); - serial_writechar('\n'); - } - } - else if (gcmd->seen_M) { - switch (gcmd->M) { - // M101- extruder on - case 101: - if (temp_achieved() == 0) { - enqueue(NULL); - } - do { - // backup feedrate, move E very quickly then restore feedrate - backup_f = startpoint.F; - startpoint.F = MAXIMUM_FEEDRATE_E; - SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); - startpoint.F = backup_f; - } while (0); - break; - - // M102- extruder reverse - - // M103- extruder off - case 103: - do { - // backup feedrate, move E very quickly then restore feedrate - backup_f = startpoint.F; - startpoint.F = MAXIMUM_FEEDRATE_E; - SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); - startpoint.F = backup_f; - } while (0); - break; - - // M104- set temperature - case 104: - temp_set(gcmd->S); - if (gcmd->S) { - enable_heater(); - power_on(); - } - else { - disable_heater(); - } - break; - - // M105- get temperature - case 105: - temp_print(); - break; - - // M106- fan on - #ifdef FAN_PIN - case 106: - enable_fan(); - break; - // M107- fan off - case 107: - disable_fan(); - break; - #endif - - // M109- set temp and wait - case 109: - temp_set(gcmd->S); - if (gcmd->S) { - enable_heater(); - power_on(); - } - else { - disable_heater(); - } - enqueue(NULL); - break; - - // M110- set line number - case 110: - gcmd->N_expected = gcmd->S - 1; - break; - // M111- set debug level - #ifdef DEBUG - case 111: - debug_flags = gcmd->S; - break; - #endif - // M112- immediate stop - case 112: - disableTimerInterrupt(); - power_off(); - break; - // M113- extruder PWM - // M114- report XYZEF to host - case 114: - sersendf_P("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n", current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); - break; - - #ifdef HEATER_PIN - // M130- heater P factor - case 130: - if (gcmd->seen_S) - p_factor = gcmd->S; - break; - // M131- heater I factor - case 131: - if (gcmd->seen_S) - i_factor = gcmd->S; - break; - // M132- heater D factor - case 132: - if (gcmd->seen_S) - d_factor = gcmd->S; - break; - // M133- heater I limit - case 133: - if (gcmd->seen_S) - i_limit = gcmd->S; - break; - // M134- save PID settings to eeprom - case 134: - heater_save_settings(); - break; - #endif /* HEATER_PIN */ - - // M190- power on - case 190: - power_on(); - #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 0); - #endif - #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 0); - #endif - #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 0); - #endif - steptimeout = 0; - break; - // M191- power off - case 191: - #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 1); - #endif - #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 1); - #endif - #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 1); - #endif - power_off(); - break; - - #ifdef DEBUG - // M140- echo off - case 140: - debug_flags &= ~DEBUG_ECHO; - serial_writestr_P(PSTR("Echo off\n")); - break; - // M141- echo on - case 141: - debug_flags |= DEBUG_ECHO; - serial_writestr_P(PSTR("Echo on\n")); - break; - - // DEBUG: return current position - case 250: - serial_writestr_P(PSTR("{X:")); - serwrite_int32(current_position.X); - serial_writestr_P(PSTR(",Y:")); - serwrite_int32(current_position.Y); - serial_writestr_P(PSTR(",Z:")); - serwrite_int32(current_position.Z); - serial_writestr_P(PSTR(",E:")); - serwrite_int32(current_position.E); - serial_writestr_P(PSTR(",F:")); - serwrite_int32(current_position.F); - serial_writestr_P(PSTR(",c:")); - serwrite_uint32(movebuffer[mb_tail].c); - serial_writestr_P(PSTR("}\n")); - - serial_writestr_P(PSTR("{X:")); - serwrite_int32(movebuffer[mb_tail].endpoint.X); - serial_writestr_P(PSTR(",Y:")); - serwrite_int32(movebuffer[mb_tail].endpoint.Y); - serial_writestr_P(PSTR(",Z:")); - serwrite_int32(movebuffer[mb_tail].endpoint.Z); - serial_writestr_P(PSTR(",E:")); - serwrite_int32(movebuffer[mb_tail].endpoint.E); - serial_writestr_P(PSTR(",F:")); - serwrite_int32(movebuffer[mb_tail].endpoint.F); - serial_writestr_P(PSTR(",c:")); - #ifdef ACCELERATION_REPRAP - serwrite_uint32(movebuffer[mb_tail].end_c); - #else - serwrite_uint32(movebuffer[mb_tail].c); - #endif - serial_writestr_P(PSTR("}\n")); - - print_queue(); - break; - - // DEBUG: read arbitrary memory location - case 253: - if (gcmd->seen_P == 0) - gcmd->P = 1; - for (; gcmd->P; gcmd->P--) { - serwrite_hex8(*(volatile uint8_t *)(gcmd->S)); - gcmd->S++; - } - serial_writechar('\n'); - break; - - // DEBUG: write arbitrary memory locatiom - case 254: - serwrite_hex8(gcmd->S); - serial_writechar(':'); - serwrite_hex8(*(volatile uint8_t *)(gcmd->S)); - serial_writestr_P(PSTR("->")); - serwrite_hex8(gcmd->P); - serial_writechar('\n'); - (*(volatile uint8_t *)(gcmd->S)) = gcmd->P; - break; - #endif /* DEBUG */ - // unknown mcode: spit an error - default: - serial_writestr_P(PSTR("E: Bad M-code ")); - serwrite_uint8(gcmd->M); - serial_writechar('\n'); - } - } -} - /**************************************************************************** * * * Request a resend of the current line - used from various places. * @@ -784,12 +403,7 @@ void process_gcode_command(GCODE_COMMAND *gcmd) { ****************************************************************************/ void request_resend(void) { - #if defined REPRAP_HOST_COMPATIBILITY && REPRAP_HOST_COMPATIBILITY >= 20100806 serial_writestr_P(PSTR("rs ")); - #else - serial_writestr_P(PSTR("Resend:")); - #endif serwrite_uint8(next_target.N); serial_writechar('\n'); } - diff --git a/gcode.h b/gcode_parse.h similarity index 91% rename from gcode.h rename to gcode_parse.h index 3c9e342..7a8dd16 100644 --- a/gcode.h +++ b/gcode_parse.h @@ -1,5 +1,5 @@ -#ifndef _GCODE_H -#define _GCODE_H +#ifndef _GCODE_PARSE_H +#define _GCODE_PARSE_H #include @@ -69,12 +69,9 @@ void SpecialMoveZ(int32_t z, uint32_t f); void SpecialMoveE(int32_t e, uint32_t f); // accept the next character and process it -void scan_char(uint8_t c); - -// when we have a whole line, feed it to this -void process_gcode_command(GCODE_COMMAND *gcmd); +void gcode_parse_char(uint8_t c); // uses the global variable next_target.N void request_resend(void); -#endif /* _GCODE_H */ +#endif /* _GCODE_PARSE_H */ diff --git a/gcode_process.c b/gcode_process.c new file mode 100644 index 0000000..2ced51b --- /dev/null +++ b/gcode_process.c @@ -0,0 +1,393 @@ +#include "gcode_process.h" + +#include + +#include "gcode_parse.h" + +#include "dda_queue.h" +#include "watchdog.h" +#include "delay.h" +#include "serial.h" +#include "sermsg.h" +#include "temp.h" +#include "heater.h" +#include "timer.h" +#include "sersendf.h" + +/**************************************************************************** +* * +* Command Received - process it * +* * +****************************************************************************/ + +void process_gcode_command() { + uint32_t backup_f; + + // convert relative to absolute + if (next_target.option_relative) { + next_target.target.X += startpoint.X; + next_target.target.Y += startpoint.Y; + next_target.target.Z += startpoint.Z; + } + // E ALWAYS relative, otherwise we overflow our registers after only a few layers + // next_target.target.E += startpoint.E; + // easier way to do this + // startpoint.E = 0; + // moved to dda.c, end of dda_create() and dda_queue.c, next_move() + + if (next_target.seen_G) { + switch (next_target.G) { + // G0 - rapid, unsynchronised motion + // since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects + case 0: + backup_f = next_target.target.F; + next_target.target.F = MAXIMUM_FEEDRATE_X * 2; + enqueue(&next_target.target); + next_target.target.F = backup_f; + break; + + // G1 - synchronised motion + case 1: + enqueue(&next_target.target); + break; + + // G2 - Arc Clockwise + // unimplemented + + // G3 - Arc Counter-clockwise + // unimplemented + + // G4 - Dwell + case 4: + // wait for all moves to complete + for (;queue_empty() == 0;) + wd_reset(); + // delay + delay_ms(next_target.P); + break; + + // G20 - inches as units + case 20: + next_target.option_inches = 1; + break; + + // G21 - mm as units + case 21: + next_target.option_inches = 0; + break; + + // G30 - go home via point + case 30: + enqueue(&next_target.target); + // no break here, G30 is move and then go home + + // G28 - go home + case 28: + /* + Home XY first + */ + // hit endstops, no acceleration- we don't care about skipped steps + startpoint.F = MAXIMUM_FEEDRATE_X; + SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, MAXIMUM_FEEDRATE_X); + startpoint.X = startpoint.Y = 0; + + // move forward a bit + SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); + + // move back in to endstops slowly + SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); + + // wait for queue to complete + for (;queue_empty() == 0;) + wd_reset(); + + // this is our home point + startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0; + + /* + Home Z + */ + // hit endstop, no acceleration- we don't care about skipped steps + startpoint.F = MAXIMUM_FEEDRATE_Z; + SpecialMoveZ(-250L * STEPS_PER_MM_Z, MAXIMUM_FEEDRATE_Z); + startpoint.Z = 0; + + // move forward a bit + SpecialMoveZ(5 * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); + + // move back into endstop slowly + SpecialMoveZ(-20L * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); + + // wait for queue to complete + for (;queue_empty() == 0;) + wd_reset(); + + // this is our home point + startpoint.Z = current_position.Z = 0; + + /* + Home E + */ + // extruder only runs one way and we have no "endstop", just set this point as home + startpoint.E = current_position.E = 0; + + /* + Home F + */ + + // F has been left at SEARCH_FEEDRATE_Z by the last move, this is a usable "home" + // uncomment the following or substitute if you prefer a different default feedrate + // startpoint.F = SEARCH_FEEDRATE_Z + + break; + + // G90 - absolute positioning + case 90: + next_target.option_relative = 0; + break; + + // G91 - relative positioning + case 91: + next_target.option_relative = 1; + break; + + // G92 - set home + case 92: + startpoint.X = startpoint.Y = startpoint.Z = startpoint.E = + current_position.X = current_position.Y = current_position.Z = current_position.E = 0; + startpoint.F = + current_position.F = SEARCH_FEEDRATE_Z; + break; + + // unknown gcode: spit an error + default: + serial_writestr_P(PSTR("E: Bad G-code ")); + serwrite_uint8(next_target.G); + serial_writechar('\n'); + } + } + else if (next_target.seen_M) { + switch (next_target.M) { + // M101- extruder on + case 101: + if (temp_achieved() == 0) { + enqueue(NULL); + } + do { + // backup feedrate, move E very quickly then restore feedrate + backup_f = startpoint.F; + startpoint.F = MAXIMUM_FEEDRATE_E; + SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); + startpoint.F = backup_f; + } while (0); + break; + + // M102- extruder reverse + + // M103- extruder off + case 103: + do { + // backup feedrate, move E very quickly then restore feedrate + backup_f = startpoint.F; + startpoint.F = MAXIMUM_FEEDRATE_E; + SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); + startpoint.F = backup_f; + } while (0); + break; + + // M104- set temperature + case 104: + temp_set(next_target.S); + if (next_target.S) { + enable_heater(); + power_on(); + } + else { + disable_heater(); + } + break; + + // M105- get temperature + case 105: + temp_print(); + break; + + // M106- fan on + #ifdef FAN_PIN + case 106: + enable_fan(); + break; + // M107- fan off + case 107: + disable_fan(); + break; + #endif + + // M109- set temp and wait + case 109: + temp_set(next_target.S); + if (next_target.S) { + enable_heater(); + power_on(); + } + else { + disable_heater(); + } + enqueue(NULL); + break; + + // M110- set line number + case 110: + next_target.N_expected = next_target.S - 1; + break; + // M111- set debug level + #ifdef DEBUG + case 111: + debug_flags = next_target.S; + break; + #endif + // M112- immediate stop + case 112: + disableTimerInterrupt(); + power_off(); + break; + // M113- extruder PWM + // M114- report XYZEF to host + case 114: + sersendf_P("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n", current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); + break; + + #ifdef HEATER_PIN + // M130- heater P factor + case 130: + if (next_target.seen_S) + p_factor = next_target.S; + break; + // M131- heater I factor + case 131: + if (next_target.seen_S) + i_factor = next_target.S; + break; + // M132- heater D factor + case 132: + if (next_target.seen_S) + d_factor = next_target.S; + break; + // M133- heater I limit + case 133: + if (next_target.seen_S) + i_limit = next_target.S; + break; + // M134- save PID settings to eeprom + case 134: + heater_save_settings(); + break; + #endif /* HEATER_PIN */ + + // M190- power on + case 190: + power_on(); + #ifdef X_ENABLE_PIN + WRITE(X_ENABLE_PIN, 0); + #endif + #ifdef Y_ENABLE_PIN + WRITE(Y_ENABLE_PIN, 0); + #endif + #ifdef Z_ENABLE_PIN + WRITE(Z_ENABLE_PIN, 0); + #endif + steptimeout = 0; + break; + // M191- power off + case 191: + #ifdef X_ENABLE_PIN + WRITE(X_ENABLE_PIN, 1); + #endif + #ifdef Y_ENABLE_PIN + WRITE(Y_ENABLE_PIN, 1); + #endif + #ifdef Z_ENABLE_PIN + WRITE(Z_ENABLE_PIN, 1); + #endif + power_off(); + break; + + #ifdef DEBUG + // M140- echo off + case 140: + debug_flags &= ~DEBUG_ECHO; + serial_writestr_P(PSTR("Echo off\n")); + break; + // M141- echo on + case 141: + debug_flags |= DEBUG_ECHO; + serial_writestr_P(PSTR("Echo on\n")); + break; + + // DEBUG: return current position + case 250: + serial_writestr_P(PSTR("{X:")); + serwrite_int32(current_position.X); + serial_writestr_P(PSTR(",Y:")); + serwrite_int32(current_position.Y); + serial_writestr_P(PSTR(",Z:")); + serwrite_int32(current_position.Z); + serial_writestr_P(PSTR(",E:")); + serwrite_int32(current_position.E); + serial_writestr_P(PSTR(",F:")); + serwrite_int32(current_position.F); + serial_writestr_P(PSTR(",c:")); + serwrite_uint32(movebuffer[mb_tail].c); + serial_writestr_P(PSTR("}\n")); + + serial_writestr_P(PSTR("{X:")); + serwrite_int32(movebuffer[mb_tail].endpoint.X); + serial_writestr_P(PSTR(",Y:")); + serwrite_int32(movebuffer[mb_tail].endpoint.Y); + serial_writestr_P(PSTR(",Z:")); + serwrite_int32(movebuffer[mb_tail].endpoint.Z); + serial_writestr_P(PSTR(",E:")); + serwrite_int32(movebuffer[mb_tail].endpoint.E); + serial_writestr_P(PSTR(",F:")); + serwrite_int32(movebuffer[mb_tail].endpoint.F); + serial_writestr_P(PSTR(",c:")); + #ifdef ACCELERATION_REPRAP + serwrite_uint32(movebuffer[mb_tail].end_c); + #else + serwrite_uint32(movebuffer[mb_tail].c); + #endif + serial_writestr_P(PSTR("}\n")); + + print_queue(); + break; + + // DEBUG: read arbitrary memory location + case 253: + if (next_target.seen_P == 0) + next_target.P = 1; + for (; next_target.P; next_target.P--) { + serwrite_hex8(*(volatile uint8_t *)(next_target.S)); + next_target.S++; + } + serial_writechar('\n'); + break; + + // DEBUG: write arbitrary memory locatiom + case 254: + serwrite_hex8(next_target.S); + serial_writechar(':'); + serwrite_hex8(*(volatile uint8_t *)(next_target.S)); + serial_writestr_P(PSTR("->")); + serwrite_hex8(next_target.P); + serial_writechar('\n'); + (*(volatile uint8_t *)(next_target.S)) = next_target.P; + break; + #endif /* DEBUG */ + // unknown mcode: spit an error + default: + serial_writestr_P(PSTR("E: Bad M-code ")); + serwrite_uint8(next_target.M); + serial_writechar('\n'); + } + } +} diff --git a/gcode_process.h b/gcode_process.h new file mode 100644 index 0000000..b872b5e --- /dev/null +++ b/gcode_process.h @@ -0,0 +1,9 @@ +#ifndef _GCODE_PROCESS_H +#define _GCODE_PROCESS_H + +#include "gcode_parse.h" + +// when we have a whole line, feed it to this +void process_gcode_command(void); + +#endif /* _GCODE_PROCESS_H */ diff --git a/mendel.c b/mendel.c index 1154ebd..5783dcb 100644 --- a/mendel.c +++ b/mendel.c @@ -7,7 +7,7 @@ #include "serial.h" #include "dda_queue.h" #include "dda.h" -#include "gcode.h" +#include "gcode_parse.h" #include "timer.h" #include "clock.h" #include "temp.h" @@ -151,7 +151,7 @@ int main (void) // if queue is full, no point in reading chars- host will just have to wait if ((serial_rxchars() != 0) && (queue_full() == 0)) { uint8_t c = serial_popchar(); - scan_char(c); + gcode_parse_char(c); } ifclock(CLOCK_FLAG_250MS) { From 21bae96b6ef78d579146deda2ed16ab6badd89e6 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 25 Oct 2010 22:48:16 +1100 Subject: [PATCH 05/82] attempt to fix precision underflow in UM_PER_STEP macros --- dda.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dda.c b/dda.c index 762fc46..d079df4 100644 --- a/dda.c +++ b/dda.c @@ -70,10 +70,10 @@ /* Used in distance calculation during DDA setup */ -#define UM_PER_STEP_X ((uint32_t) ((1000.0 / STEPS_PER_MM_X) + 0.5)) -#define UM_PER_STEP_Y ((uint32_t) ((1000.0 / STEPS_PER_MM_Y) + 0.5)) -#define UM_PER_STEP_Z ((uint32_t) ((1000.0 / STEPS_PER_MM_Z) + 0.5)) -#define UM_PER_STEP_E ((uint32_t) ((1000.0 / STEPS_PER_MM_E) + 0.5)) +#define UM_PER_STEP_X 1000L / ((uint32_t) STEPS_PER_MM_X) +#define UM_PER_STEP_Y 1000L / ((uint32_t) STEPS_PER_MM_Y) +#define UM_PER_STEP_Z 1000L / ((uint32_t) STEPS_PER_MM_Z) +#define UM_PER_STEP_E 1000L / ((uint32_t) STEPS_PER_MM_E) /* Maths @@ -271,16 +271,16 @@ void dda_create(DDA *dda, TARGET *target) { // similarly, find out how fast we can run our axes. // do this for each axis individually, as the combined speed of two or more axes can be higher than the capabilities of a single one. c_limit = 0; - c_limit_calc = ((dda->x_delta * UM_PER_STEP_X * 2400) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8; + c_limit_calc = ( (dda->x_delta * (UM_PER_STEP_X * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; - c_limit_calc = ((dda->y_delta * UM_PER_STEP_Y * 2400) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Y) << 8; + c_limit_calc = ( (dda->y_delta * (UM_PER_STEP_Y * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Y) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; - c_limit_calc = ((dda->z_delta * UM_PER_STEP_Z * 2400) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Z) << 8; + c_limit_calc = ( (dda->z_delta * (UM_PER_STEP_Z * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Z) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; - c_limit_calc = ((dda->e_delta * UM_PER_STEP_E * 2400) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_E) << 8; + c_limit_calc = ( (dda->e_delta * (UM_PER_STEP_E * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_E) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; From ea2c7cd469887fdafd53a34cbeca5ee3cca36862 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 18 Oct 2010 18:38:14 +1100 Subject: [PATCH 06/82] split arduino pin definitions out into different files --- arduino.h | 744 +-------------------------------------------- arduino_1280.h | 385 +++++++++++++++++++++++ arduino_168_328p.h | 127 ++++++++ arduino_644.h | 227 ++++++++++++++ 4 files changed, 742 insertions(+), 741 deletions(-) create mode 100644 arduino_1280.h create mode 100644 arduino_168_328p.h create mode 100644 arduino_644.h diff --git a/arduino.h b/arduino.h index bd65c98..d80089b 100644 --- a/arduino.h +++ b/arduino.h @@ -46,753 +46,15 @@ */ #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) - // UART - #define RXD DIO0 - #define TXD DIO1 - - // SPI - #define SCK DIO13 - #define MISO DIO12 - #define MOSI DIO11 - #define SS DIO10 - - // TWI (I2C) - #define SCL AIO5 - #define SDA AIO4 - - // timers and PWM - #define OC0A DIO6 - #define OC0B DIO5 - #define OC1A DIO9 - #define OC1B DIO10 - #define OC2A DIO11 - #define OC2B DIO3 - - #define ICP1 DIO8 - - /* - pins - */ - - #define DIO0_PIN PIND0 - #define DIO0_RPORT PIND - #define DIO0_WPORT PORTD - #define DIO0_DDR DDRD - - #define DIO1_PIN PIND1 - #define DIO1_RPORT PIND - #define DIO1_WPORT PORTD - #define DIO1_DDR DDRD - - #define DIO2_PIN PIND2 - #define DIO2_RPORT PIND - #define DIO2_WPORT PORTD - #define DIO2_DDR DDRD - - #define DIO3_PIN PIND3 - #define DIO3_RPORT PIND - #define DIO3_WPORT PORTD - #define DIO3_DDR DDRD - - #define DIO4_PIN PIND4 - #define DIO4_RPORT PIND - #define DIO4_WPORT PORTD - #define DIO4_DDR DDRD - - #define DIO5_PIN PIND5 - #define DIO5_RPORT PIND - #define DIO5_WPORT PORTD - #define DIO5_DDR DDRD - - #define DIO6_PIN PIND6 - #define DIO6_RPORT PIND - #define DIO6_WPORT PORTD - #define DIO6_DDR DDRD - - #define DIO7_PIN PIND7 - #define DIO7_RPORT PIND - #define DIO7_WPORT PORTD - #define DIO7_DDR DDRD - - #define DIO8_PIN PINB0 - #define DIO8_RPORT PINB - #define DIO8_WPORT PORTB - #define DIO8_DDR DDRB - - #define DIO9_PIN PINB1 - #define DIO9_RPORT PINB - #define DIO9_WPORT PORTB - #define DIO9_DDR DDRB - - #define DIO10_PIN PINB2 - #define DIO10_RPORT PINB - #define DIO10_WPORT PORTB - #define DIO10_DDR DDRB - - #define DIO11_PIN PINB3 - #define DIO11_RPORT PINB - #define DIO11_WPORT PORTB - #define DIO11_DDR DDRB - - #define DIO12_PIN PINB4 - #define DIO12_RPORT PINB - #define DIO12_WPORT PORTB - #define DIO12_DDR DDRB - - #define DIO13_PIN PINB5 - #define DIO13_RPORT PINB - #define DIO13_WPORT PORTB - #define DIO13_DDR DDRB - - #define AIO0_PIN PINC0 - #define AIO0_RPORT PINC - #define AIO0_WPORT PORTC - #define AIO0_DDR DDRC - - #define AIO1_PIN PINC1 - #define AIO1_RPORT PINC - #define AIO1_WPORT PORTC - #define AIO1_DDR DDRC - - #define AIO2_PIN PINC2 - #define AIO2_RPORT PINC - #define AIO2_WPORT PORTC - #define AIO2_DDR DDRC - - #define AIO3_PIN PINC3 - #define AIO3_RPORT PINC - #define AIO3_WPORT PORTC - #define AIO3_DDR DDRC - - #define AIO4_PIN PINC4 - #define AIO4_RPORT PINC - #define AIO4_WPORT PORTC - #define AIO4_DDR DDRC - - #define AIO5_PIN PINC5 - #define AIO5_RPORT PINC - #define AIO5_WPORT PORTC - #define AIO5_DDR DDRC + #include "arduino_168_328p.h" #endif /* _AVR_ATmega{168,328,328P}__) */ #if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) - // UART - #define RXD DIO0 - #define TXD DIO1 - - // SPI - #define SCK DIO13 - #define MISO DIO12 - #define MOSI DIO11 - #define SS DIO10 - - // TWI (I2C) - #define SCL AIO5 - #define SDA AIO4 - - // timers and PWM - #define OC0A DIO6 - #define OC0B DIO5 - #define OC1A DIO9 - #define OC1B DIO10 - #define OC2A DIO11 - #define OC2B DIO3 - - #define ICP1 DIO8 - - /* - pins - */ - - #define DIO0_PIN PINB0 - #define DIO0_RPORT PINB - #define DIO0_WPORT PORTB - #define DIO0_DDR DDRB - - #define DIO1_PIN PINB1 - #define DIO1_RPORT PINB - #define DIO1_WPORT PORTB - #define DIO1_DDR DDRB - - #define DIO2_PIN PINB2 - #define DIO2_RPORT PINB - #define DIO2_WPORT PORTB - #define DIO2_DDR DDRB - - #define DIO3_PIN PINB3 - #define DIO3_RPORT PINB - #define DIO3_WPORT PORTB - #define DIO3_DDR DDRB - - #define DIO4_PIN PINB4 - #define DIO4_RPORT PINB - #define DIO4_WPORT PORTB - #define DIO4_DDR DDRB - - #define DIO5_PIN PINB5 - #define DIO5_RPORT PINB - #define DIO5_WPORT PORTB - #define DIO5_DDR DDRB - - #define DIO6_PIN PINB6 - #define DIO6_RPORT PINB - #define DIO6_WPORT PORTB - #define DIO6_DDR DDRB - - #define DIO7_PIN PINB7 - #define DIO7_RPORT PINB - #define DIO7_WPORT PORTB - #define DIO7_DDR DDRB - - #define DIO8_PIN PIND0 - #define DIO8_RPORT PIND - #define DIO8_WPORT PORTD - #define DIO8_DDR DDRD - - #define DIO9_PIN PIND1 - #define DIO9_RPORT PIND - #define DIO9_WPORT PORTD - #define DIO9_DDR DDRD - - #define DIO10_PIN PIND2 - #define DIO10_RPORT PIND - #define DIO10_WPORT PORTD - #define DIO10_DDR DDRD - - #define DIO11_PIN PIND3 - #define DIO11_RPORT PIND - #define DIO11_WPORT PORTD - #define DIO11_DDR DDRD - - #define DIO12_PIN PIND4 - #define DIO12_RPORT PIND - #define DIO12_WPORT PORTD - #define DIO12_DDR DDRD - - #define DIO13_PIN PIND5 - #define DIO13_RPORT PIND - #define DIO13_WPORT PORTD - #define DIO13_DDR DDRD - - #define DIO14_PIN PIND6 - #define DIO14_RPORT PIND - #define DIO14_WPORT PORTD - #define DIO14_DDR DDRD - - #define DIO15_PIN PIND7 - #define DIO15_RPORT PIND - #define DIO15_WPORT PORTD - #define DIO15_DDR DDRD - - #define DIO16_PIN PINC0 - #define DIO16_RPORT PINC - #define DIO16_WPORT PORTC - #define DIO16_DDR DDRC - - #define DIO17_PIN PINC1 - #define DIO17_RPORT PINC - #define DIO17_WPORT PORTC - #define DIO17_DDR DDRC - - #define DIO18_PIN PINC2 - #define DIO18_RPORT PINC - #define DIO18_WPORT PORTC - #define DIO18_DDR DDRC - - #define DIO19_PIN PINC3 - #define DIO19_RPORT PINC - #define DIO19_WPORT PORTC - #define DIO19_DDR DDRC - - #define DIO20_PIN PINC4 - #define DIO20_RPORT PINC - #define DIO20_WPORT PORTC - #define DIO20_DDR DDRC - - #define DIO21_PIN PINC5 - #define DIO21_RPORT PINC - #define DIO21_WPORT PORTC - #define DIO21_DDR DDRC - - #define DIO22_PIN PINC6 - #define DIO22_RPORT PINC - #define DIO22_WPORT PORTC - #define DIO22_DDR DDRC - - #define DIO23_PIN PINC7 - #define DIO23_RPORT PINC - #define DIO23_WPORT PORTC - #define DIO23_DDR DDRC - - #define DIO24_PIN PINA7 - #define DIO24_RPORT PINA - #define DIO24_WPORT PORTA - #define DIO24_DDR DDRA - - #define DIO25_PIN PINA6 - #define DIO25_RPORT PINA - #define DIO25_WPORT PORTA - #define DIO25_DDR DDRA - - #define DIO26_PIN PINA5 - #define DIO26_RPORT PINA - #define DIO26_WPORT PORTA - #define DIO26_DDR DDRA - - #define DIO27_PIN PINA4 - #define DIO27_RPORT PINA - #define DIO27_WPORT PORTA - #define DIO27_DDR DDRA - - #define DIO28_PIN PINA3 - #define DIO28_RPORT PINA - #define DIO28_WPORT PORTA - #define DIO28_DDR DDRA - - #define DIO29_PIN PINA2 - #define DIO29_RPORT PINA - #define DIO29_WPORT PORTA - #define DIO29_DDR DDRA - - #define DIO30_PIN PINA1 - #define DIO30_RPORT PINA - #define DIO30_WPORT PORTA - #define DIO30_DDR DDRA - - #define DIO31_PIN PINA0 - #define DIO31_RPORT PINA - #define DIO31_WPORT PORTA - #define DIO31_DDR DDRA - - #define AIO0_PIN PINA0 - #define AIO0_RPORT PINA - #define AIO0_WPORT PORTA - #define AIO0_DDR DDRA - - #define AIO1_PIN PINA1 - #define AIO1_RPORT PINA - #define AIO1_WPORT PORTA - #define AIO1_DDR DDRA - - #define AIO2_PIN PINA2 - #define AIO2_RPORT PINA - #define AIO2_WPORT PORTA - #define AIO2_DDR DDRA - - #define AIO3_PIN PINA3 - #define AIO3_RPORT PINA - #define AIO3_WPORT PORTA - #define AIO3_DDR DDRA - - #define AIO4_PIN PINA4 - #define AIO4_RPORT PINA - #define AIO4_WPORT PORTA - #define AIO4_DDR DDRA - - #define AIO5_PIN PINA5 - #define AIO5_RPORT PINA - #define AIO5_WPORT PORTA - #define AIO5_DDR DDRA - - #define AIO6_PIN PINA6 - #define AIO6_RPORT PINA - #define AIO6_WPORT PORTA - #define AIO6_DDR DDRA - - #define AIO7_PIN PINA7 - #define AIO7_RPORT PINA - #define AIO7_WPORT PORTA - #define AIO7_DDR DDRA + #include "arduino_644.h" #endif #if defined (__AVR_ATmega1280__) - - // UART - #define RXD DIO0 - #define TXD DIO1 - - // SPI - #define SCK DIO52 - #define MISO DIO50 - #define MOSI DIO51 - #define SS DIO53 - - // TWI (I2C) - #define SCL DIO21 - #define SDA DIO20 - - // timers and PWM - #define OC0A DIO13 - #define OC0B DIO4 - #define OC1A DIO11 - #define OC1B DIO12 - #define OC2A DIO10 - #define OC2B DIO9 - #define OC3A DIO5 - #define OC3B DIO2 - #define OC3C DIO3 - #define OC4A DIO6 - #define OC4B DIO7 - #define OC4C DIO8 - #define OC5A DIO46 - #define OC5B DIO45 - #define OC5C DIO44 - -// #define ICP1 NULL /* not brought out on the Arduino Mega, remove line as not used ?? */ - - /* - pins - */ - #define DIO0_PIN PINE0 - #define DIO0_RPORT PINE - #define DIO0_WPORT PORTE - #define DIO0_DDR DDRE - - #define DIO1_PIN PINE1 - #define DIO1_RPORT PINE - #define DIO1_WPORT PORTE - #define DIO1_DDR DDRE - - #define DIO2_PIN PINE4 - #define DIO2_RPORT PINE - #define DIO2_WPORT PORTE - #define DIO2_DDR DDRE - - #define DIO3_PIN PINE5 - #define DIO3_RPORT PINE - #define DIO3_WPORT PORTE - #define DIO3_DDR DDRE - - #define DIO4_PIN PING5 - #define DIO4_RPORT PING - #define DIO4_WPORT PORTG - #define DIO4_DDR DDRG - - #define DIO5_PIN PINE3 - #define DIO5_RPORT PINE - #define DIO5_WPORT PORTE - #define DIO5_DDR DDRE - - #define DIO6_PIN PINH3 - #define DIO6_RPORT PINH - #define DIO6_WPORT PORTH - #define DIO6_DDR DDRH - - #define DIO7_PIN PINH4 - #define DIO7_RPORT PINH - #define DIO7_WPORT PORTH - #define DIO7_DDR DDRH - - #define DIO8_PIN PINH5 - #define DIO8_RPORT PINH - #define DIO8_WPORT PORTH - #define DIO8_DDR DDRH - - #define DIO9_PIN PINH6 - #define DIO9_RPORT PINH - #define DIO9_WPORT PORTH - #define DIO9_DDR DDRH - - #define DIO10_PIN PINB4 - #define DIO10_RPORT PINB - #define DIO10_WPORT PORTB - #define DIO10_DDR DDRB - - #define DIO11_PIN PINB5 - #define DIO11_RPORT PINB - #define DIO11_WPORT PORTB - #define DIO11_DDR DDRB - - #define DIO12_PIN PINB6 - #define DIO12_RPORT PINB - #define DIO12_WPORT PORTB - #define DIO12_DDR DDRB - - #define DIO13_PIN PINB7 - #define DIO13_RPORT PINB - #define DIO13_WPORT PORTB - #define DIO13_DDR DDRB - - #define DIO14_PIN PINJ1 - #define DIO14_RPORT PINJ - #define DIO14_WPORT PORTJ - #define DIO14_DDR DDRJ - - #define DIO15_PIN PINJ0 - #define DIO15_RPORT PINJ - #define DIO15_WPORT PORTJ - #define DIO15_DDR DDRJ - - #define DIO16_PIN PINH1 - #define DIO16_RPORT PINH - #define DIO16_WPORT PORTH - #define DIO16_DDR DDRH - - #define DIO17_PIN PINH0 - #define DIO17_RPORT PINH - #define DIO17_WPORT PORTH - #define DIO17_DDR DDRH - - #define DIO18_PIN PIND3 - #define DIO18_RPORT PIND - #define DIO18_WPORT PORTD - #define DIO18_DDR DDRD - - #define DIO19_PIN PIND2 - #define DIO19_RPORT PIND - #define DIO19_WPORT PORTD - #define DIO19_DDR DDRD - - #define DIO20_PIN PIND1 - #define DIO20_RPORT PIND - #define DIO20_WPORT PORTD - #define DIO20_DDR DDRD - - #define DIO21_PIN PIND0 - #define DIO21_RPORT PIND - #define DIO21_WPORT PORTD - #define DIO21_DDR DDRD - - #define DIO22_PIN PINA0 - #define DIO22_RPORT PINA - #define DIO22_WPORT PORTA - #define DIO22_DDR DDRA - - #define DIO23_PIN PINA1 - #define DIO23_RPORT PINA - #define DIO23_WPORT PORTA - #define DIO23_DDR DDRA - - #define DIO24_PIN PINA2 - #define DIO24_RPORT PINA - #define DIO24_WPORT PORTA - #define DIO24_DDR DDRA - - #define DIO25_PIN PINA3 - #define DIO25_RPORT PINA - #define DIO25_WPORT PORTA - #define DIO25_DDR DDRA - - #define DIO26_PIN PINA4 - #define DIO26_RPORT PINA - #define DIO26_WPORT PORTA - #define DIO26_DDR DDRA - - #define DIO27_PIN PINA5 - #define DIO27_RPORT PINA - #define DIO27_WPORT PORTA - #define DIO27_DDR DDRA - - #define DIO28_PIN PINA6 - #define DIO28_RPORT PINA - #define DIO28_WPORT PORTA - #define DIO28_DDR DDRA - - #define DIO29_PIN PINA7 - #define DIO29_RPORT PINA - #define DIO29_WPORT PORTA - #define DIO29_DDR DDRA - - #define DIO30_PIN PINC7 - #define DIO30_RPORT PINC - #define DIO30_WPORT PORTC - #define DIO30_DDR DDRC - - #define DIO31_PIN PINC6 - #define DIO31_RPORT PINC - #define DIO31_WPORT PORTC - #define DIO31_DDR DDRC - - #define DIO32_PIN PINC5 - #define DIO32_RPORT PINC - #define DIO32_WPORT PORTC - #define DIO32_DDR DDRC - - #define DIO33_PIN PINC4 - #define DIO33_RPORT PINC - #define DIO33_WPORT PORTC - #define DIO33_DDR DDRC - - #define DIO34_PIN PINC3 - #define DIO34_RPORT PINC - #define DIO34_WPORT PORTC - #define DIO34_DDR DDRC - - #define DIO35_PIN PINC2 - #define DIO35_RPORT PINC - #define DIO35_WPORT PORTC - #define DIO35_DDR DDRC - - #define DIO36_PIN PINC1 - #define DIO36_RPORT PINC - #define DIO36_WPORT PORTC - #define DIO36_DDR DDRC - - #define DIO37_PIN PINC0 - #define DIO37_RPORT PINC - #define DIO37_WPORT PORTC - #define DIO37_DDR DDRC - - #define DIO38_PIN PIND7 - #define DIO38_RPORT PIND - #define DIO38_WPORT PORTD - #define DIO38_DDR DDRD - - #define DIO39_PIN PING2 - #define DIO39_RPORT PING - #define DIO39_WPORT PORTG - #define DIO39_DDR DDRG - - #define DIO40_PIN PING1 - #define DIO40_RPORT PING - #define DIO40_WPORT PORTG - #define DIO40_DDR DDRG - - #define DIO41_PIN PING0 - #define DIO41_RPORT PING - #define DIO41_WPORT PORTG - #define DIO41_DDR DDRG - - #define DIO42_PIN PINL7 - #define DIO42_RPORT PINL - #define DIO42_WPORT PORTL - #define DIO42_DDR DDRL - - #define DIO43_PIN PINL6 - #define DIO43_RPORT PINL - #define DIO43_WPORT PORTL - #define DIO43_DDR DDRL - - #define DIO44_PIN PINL5 - #define DIO44_RPORT PINL - #define DIO44_WPORT PORTL - #define DIO44_DDR DDRL - - #define DIO45_PIN PINL4 - #define DIO45_RPORT PINL - #define DIO45_WPORT PORTL - #define DIO45_DDR DDRL - - #define DIO46_PIN PINL3 - #define DIO46_RPORT PINL - #define DIO46_WPORT PORTL - #define DIO46_DDR DDRL - - #define DIO47_PIN PINL2 - #define DIO47_RPORT PINL - #define DIO47_WPORT PORTL - #define DIO47_DDR DDRL - - #define DIO48_PIN PINL1 - #define DIO48_RPORT PINL - #define DIO48_WPORT PORTL - #define DIO48_DDR DDRL - - #define DIO49_PIN PINL0 - #define DIO49_RPORT PINL - #define DIO49_WPORT PORTL - #define DIO49_DDR DDRL - - #define DIO50_PIN PINB3 - #define DIO50_RPORT PINB - #define DIO50_WPORT PORTB - #define DIO50_DDR DDRB - - #define DIO51_PIN PINB2 - #define DIO51_RPORT PINB - #define DIO51_WPORT PORTB - #define DIO51_DDR DDRB - - #define DIO52_PIN PINB1 - #define DIO52_RPORT PINB - #define DIO52_WPORT PORTB - #define DIO52_DDR DDRB - - #define DIO53_PIN PINB0 - #define DIO53_RPORT PINB - #define DIO53_WPORT PORTB - #define DIO53_DDR DDRB - - #define AIO0_PIN PINF0 - #define AIO0_RPORT PINF - #define AIO0_WPORT PORTF - #define AIO0_DDR DDRF - - #define AIO1_PIN PINF1 - #define AIO1_RPORT PINF - #define AIO1_WPORT PORTF - #define AIO1_DDR DDRF - - #define AIO2_PIN PINF2 - #define AIO2_RPORT PINF - #define AIO2_WPORT PORTF - #define AIO2_DDR DDRF - - #define AIO3_PIN PINF3 - #define AIO3_RPORT PINF - #define AIO3_WPORT PORTF - #define AIO3_DDR DDRF - - #define AIO4_PIN PINF4 - #define AIO4_RPORT PINF - #define AIO4_WPORT PORTF - #define AIO4_DDR DDRF - - #define AIO5_PIN PINF5 - #define AIO5_RPORT PINF - #define AIO5_WPORT PORTF - #define AIO5_DDR DDRF - - #define AIO6_PIN PINF6 - #define AIO6_RPORT PINF - #define AIO6_WPORT PORTF - #define AIO6_DDR DDRF - - #define AIO7_PIN PINF7 - #define AIO7_RPORT PINF - #define AIO7_WPORT PORTF - #define AIO7_DDR DDRF - - #define AIO8_PIN PINK0 - #define AIO8_RPORT PINK - #define AIO8_WPORT PORTK - #define AIO8_DDR DDRK - - #define AIO9_PIN PINK1 - #define AIO9_RPORT PINK - #define AIO9_WPORT PORTK - #define AIO9_DDR DDRK - - #define AIO10_PIN PINK2 - #define AIO10_RPORT PINK - #define AIO10_WPORT PORTK - #define AIO10_DDR DDRK - - #define AIO11_PIN PINK3 - #define AIO11_RPORT PINK - #define AIO11_WPORT PORTK - #define AIO11_DDR DDRK - - #define AIO12_PIN PINK4 - #define AIO12_RPORT PINK - #define AIO12_WPORT PORTK - #define AIO12_DDR DDRK - - #define AIO13_PIN PINK5 - #define AIO13_RPORT PINK - #define AIO13_WPORT PORTK - #define AIO13_DDR DDRK - - #define AIO14_PIN PINK6 - #define AIO14_RPORT PINK - #define AIO14_WPORT PORTK - #define AIO14_DDR DDRK - - #define AIO15_PIN PINK7 - #define AIO15_RPORT PINK - #define AIO15_WPORT PORTK - #define AIO15_DDR DDRK - + #include "arduino_1280.h" #endif /* __AVR_ATmega1280__) */ #ifndef DIO0_PIN diff --git a/arduino_1280.h b/arduino_1280.h new file mode 100644 index 0000000..81594db --- /dev/null +++ b/arduino_1280.h @@ -0,0 +1,385 @@ +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO52 +#define MISO DIO50 +#define MOSI DIO51 +#define SS DIO53 + +// TWI (I2C) +#define SCL DIO21 +#define SDA DIO20 + +// timers and PWM +#define OC0A DIO13 +#define OC0B DIO4 +#define OC1A DIO11 +#define OC1B DIO12 +#define OC2A DIO10 +#define OC2B DIO9 +#define OC3A DIO5 +#define OC3B DIO2 +#define OC3C DIO3 +#define OC4A DIO6 +#define OC4B DIO7 +#define OC4C DIO8 +#define OC5A DIO46 +#define OC5B DIO45 +#define OC5C DIO44 + +// #define ICP1 NULL /* not brought out on the Arduino Mega, remove line as not used ?? */ + +/* +pins +*/ +#define DIO0_PIN PINE0 +#define DIO0_RPORT PINE +#define DIO0_WPORT PORTE +#define DIO0_DDR DDRE + +#define DIO1_PIN PINE1 +#define DIO1_RPORT PINE +#define DIO1_WPORT PORTE +#define DIO1_DDR DDRE + +#define DIO2_PIN PINE4 +#define DIO2_RPORT PINE +#define DIO2_WPORT PORTE +#define DIO2_DDR DDRE + +#define DIO3_PIN PINE5 +#define DIO3_RPORT PINE +#define DIO3_WPORT PORTE +#define DIO3_DDR DDRE + +#define DIO4_PIN PING5 +#define DIO4_RPORT PING +#define DIO4_WPORT PORTG +#define DIO4_DDR DDRG + +#define DIO5_PIN PINE3 +#define DIO5_RPORT PINE +#define DIO5_WPORT PORTE +#define DIO5_DDR DDRE + +#define DIO6_PIN PINH3 +#define DIO6_RPORT PINH +#define DIO6_WPORT PORTH +#define DIO6_DDR DDRH + +#define DIO7_PIN PINH4 +#define DIO7_RPORT PINH +#define DIO7_WPORT PORTH +#define DIO7_DDR DDRH + +#define DIO8_PIN PINH5 +#define DIO8_RPORT PINH +#define DIO8_WPORT PORTH +#define DIO8_DDR DDRH + +#define DIO9_PIN PINH6 +#define DIO9_RPORT PINH +#define DIO9_WPORT PORTH +#define DIO9_DDR DDRH + +#define DIO10_PIN PINB4 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB + +#define DIO11_PIN PINB5 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB + +#define DIO12_PIN PINB6 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB + +#define DIO13_PIN PINB7 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB + +#define DIO14_PIN PINJ1 +#define DIO14_RPORT PINJ +#define DIO14_WPORT PORTJ +#define DIO14_DDR DDRJ + +#define DIO15_PIN PINJ0 +#define DIO15_RPORT PINJ +#define DIO15_WPORT PORTJ +#define DIO15_DDR DDRJ + +#define DIO16_PIN PINH1 +#define DIO16_RPORT PINH +#define DIO16_WPORT PORTH +#define DIO16_DDR DDRH + +#define DIO17_PIN PINH0 +#define DIO17_RPORT PINH +#define DIO17_WPORT PORTH +#define DIO17_DDR DDRH + +#define DIO18_PIN PIND3 +#define DIO18_RPORT PIND +#define DIO18_WPORT PORTD +#define DIO18_DDR DDRD + +#define DIO19_PIN PIND2 +#define DIO19_RPORT PIND +#define DIO19_WPORT PORTD +#define DIO19_DDR DDRD + +#define DIO20_PIN PIND1 +#define DIO20_RPORT PIND +#define DIO20_WPORT PORTD +#define DIO20_DDR DDRD + +#define DIO21_PIN PIND0 +#define DIO21_RPORT PIND +#define DIO21_WPORT PORTD +#define DIO21_DDR DDRD + +#define DIO22_PIN PINA0 +#define DIO22_RPORT PINA +#define DIO22_WPORT PORTA +#define DIO22_DDR DDRA + +#define DIO23_PIN PINA1 +#define DIO23_RPORT PINA +#define DIO23_WPORT PORTA +#define DIO23_DDR DDRA + +#define DIO24_PIN PINA2 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA + +#define DIO25_PIN PINA3 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA + +#define DIO26_PIN PINA4 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA + +#define DIO27_PIN PINA5 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA + +#define DIO28_PIN PINA6 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA + +#define DIO29_PIN PINA7 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA + +#define DIO30_PIN PINC7 +#define DIO30_RPORT PINC +#define DIO30_WPORT PORTC +#define DIO30_DDR DDRC + +#define DIO31_PIN PINC6 +#define DIO31_RPORT PINC +#define DIO31_WPORT PORTC +#define DIO31_DDR DDRC + +#define DIO32_PIN PINC5 +#define DIO32_RPORT PINC +#define DIO32_WPORT PORTC +#define DIO32_DDR DDRC + +#define DIO33_PIN PINC4 +#define DIO33_RPORT PINC +#define DIO33_WPORT PORTC +#define DIO33_DDR DDRC + +#define DIO34_PIN PINC3 +#define DIO34_RPORT PINC +#define DIO34_WPORT PORTC +#define DIO34_DDR DDRC + +#define DIO35_PIN PINC2 +#define DIO35_RPORT PINC +#define DIO35_WPORT PORTC +#define DIO35_DDR DDRC + +#define DIO36_PIN PINC1 +#define DIO36_RPORT PINC +#define DIO36_WPORT PORTC +#define DIO36_DDR DDRC + +#define DIO37_PIN PINC0 +#define DIO37_RPORT PINC +#define DIO37_WPORT PORTC +#define DIO37_DDR DDRC + +#define DIO38_PIN PIND7 +#define DIO38_RPORT PIND +#define DIO38_WPORT PORTD +#define DIO38_DDR DDRD + +#define DIO39_PIN PING2 +#define DIO39_RPORT PING +#define DIO39_WPORT PORTG +#define DIO39_DDR DDRG + +#define DIO40_PIN PING1 +#define DIO40_RPORT PING +#define DIO40_WPORT PORTG +#define DIO40_DDR DDRG + +#define DIO41_PIN PING0 +#define DIO41_RPORT PING +#define DIO41_WPORT PORTG +#define DIO41_DDR DDRG + +#define DIO42_PIN PINL7 +#define DIO42_RPORT PINL +#define DIO42_WPORT PORTL +#define DIO42_DDR DDRL + +#define DIO43_PIN PINL6 +#define DIO43_RPORT PINL +#define DIO43_WPORT PORTL +#define DIO43_DDR DDRL + +#define DIO44_PIN PINL5 +#define DIO44_RPORT PINL +#define DIO44_WPORT PORTL +#define DIO44_DDR DDRL + +#define DIO45_PIN PINL4 +#define DIO45_RPORT PINL +#define DIO45_WPORT PORTL +#define DIO45_DDR DDRL + +#define DIO46_PIN PINL3 +#define DIO46_RPORT PINL +#define DIO46_WPORT PORTL +#define DIO46_DDR DDRL + +#define DIO47_PIN PINL2 +#define DIO47_RPORT PINL +#define DIO47_WPORT PORTL +#define DIO47_DDR DDRL + +#define DIO48_PIN PINL1 +#define DIO48_RPORT PINL +#define DIO48_WPORT PORTL +#define DIO48_DDR DDRL + +#define DIO49_PIN PINL0 +#define DIO49_RPORT PINL +#define DIO49_WPORT PORTL +#define DIO49_DDR DDRL + +#define DIO50_PIN PINB3 +#define DIO50_RPORT PINB +#define DIO50_WPORT PORTB +#define DIO50_DDR DDRB + +#define DIO51_PIN PINB2 +#define DIO51_RPORT PINB +#define DIO51_WPORT PORTB +#define DIO51_DDR DDRB + +#define DIO52_PIN PINB1 +#define DIO52_RPORT PINB +#define DIO52_WPORT PORTB +#define DIO52_DDR DDRB + +#define DIO53_PIN PINB0 +#define DIO53_RPORT PINB +#define DIO53_WPORT PORTB +#define DIO53_DDR DDRB + +#define AIO0_PIN PINF0 +#define AIO0_RPORT PINF +#define AIO0_WPORT PORTF +#define AIO0_DDR DDRF + +#define AIO1_PIN PINF1 +#define AIO1_RPORT PINF +#define AIO1_WPORT PORTF +#define AIO1_DDR DDRF + +#define AIO2_PIN PINF2 +#define AIO2_RPORT PINF +#define AIO2_WPORT PORTF +#define AIO2_DDR DDRF + +#define AIO3_PIN PINF3 +#define AIO3_RPORT PINF +#define AIO3_WPORT PORTF +#define AIO3_DDR DDRF + +#define AIO4_PIN PINF4 +#define AIO4_RPORT PINF +#define AIO4_WPORT PORTF +#define AIO4_DDR DDRF + +#define AIO5_PIN PINF5 +#define AIO5_RPORT PINF +#define AIO5_WPORT PORTF +#define AIO5_DDR DDRF + +#define AIO6_PIN PINF6 +#define AIO6_RPORT PINF +#define AIO6_WPORT PORTF +#define AIO6_DDR DDRF + +#define AIO7_PIN PINF7 +#define AIO7_RPORT PINF +#define AIO7_WPORT PORTF +#define AIO7_DDR DDRF + +#define AIO8_PIN PINK0 +#define AIO8_RPORT PINK +#define AIO8_WPORT PORTK +#define AIO8_DDR DDRK + +#define AIO9_PIN PINK1 +#define AIO9_RPORT PINK +#define AIO9_WPORT PORTK +#define AIO9_DDR DDRK + +#define AIO10_PIN PINK2 +#define AIO10_RPORT PINK +#define AIO10_WPORT PORTK +#define AIO10_DDR DDRK + +#define AIO11_PIN PINK3 +#define AIO11_RPORT PINK +#define AIO11_WPORT PORTK +#define AIO11_DDR DDRK + +#define AIO12_PIN PINK4 +#define AIO12_RPORT PINK +#define AIO12_WPORT PORTK +#define AIO12_DDR DDRK + +#define AIO13_PIN PINK5 +#define AIO13_RPORT PINK +#define AIO13_WPORT PORTK +#define AIO13_DDR DDRK + +#define AIO14_PIN PINK6 +#define AIO14_RPORT PINK +#define AIO14_WPORT PORTK +#define AIO14_DDR DDRK + +#define AIO15_PIN PINK7 +#define AIO15_RPORT PINK +#define AIO15_WPORT PORTK +#define AIO15_DDR DDRK diff --git a/arduino_168_328p.h b/arduino_168_328p.h new file mode 100644 index 0000000..77b3242 --- /dev/null +++ b/arduino_168_328p.h @@ -0,0 +1,127 @@ +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define ICP1 DIO8 + +/* +pins +*/ + +#define DIO0_PIN PIND0 +#define DIO0_RPORT PIND +#define DIO0_WPORT PORTD +#define DIO0_DDR DDRD + +#define DIO1_PIN PIND1 +#define DIO1_RPORT PIND +#define DIO1_WPORT PORTD +#define DIO1_DDR DDRD + +#define DIO2_PIN PIND2 +#define DIO2_RPORT PIND +#define DIO2_WPORT PORTD +#define DIO2_DDR DDRD + +#define DIO3_PIN PIND3 +#define DIO3_RPORT PIND +#define DIO3_WPORT PORTD +#define DIO3_DDR DDRD + +#define DIO4_PIN PIND4 +#define DIO4_RPORT PIND +#define DIO4_WPORT PORTD +#define DIO4_DDR DDRD + +#define DIO5_PIN PIND5 +#define DIO5_RPORT PIND +#define DIO5_WPORT PORTD +#define DIO5_DDR DDRD + +#define DIO6_PIN PIND6 +#define DIO6_RPORT PIND +#define DIO6_WPORT PORTD +#define DIO6_DDR DDRD + +#define DIO7_PIN PIND7 +#define DIO7_RPORT PIND +#define DIO7_WPORT PORTD +#define DIO7_DDR DDRD + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_DDR DDRB + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_DDR DDRB + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB + +#define AIO0_PIN PINC0 +#define AIO0_RPORT PINC +#define AIO0_WPORT PORTC +#define AIO0_DDR DDRC + +#define AIO1_PIN PINC1 +#define AIO1_RPORT PINC +#define AIO1_WPORT PORTC +#define AIO1_DDR DDRC + +#define AIO2_PIN PINC2 +#define AIO2_RPORT PINC +#define AIO2_WPORT PORTC +#define AIO2_DDR DDRC + +#define AIO3_PIN PINC3 +#define AIO3_RPORT PINC +#define AIO3_WPORT PORTC +#define AIO3_DDR DDRC + +#define AIO4_PIN PINC4 +#define AIO4_RPORT PINC +#define AIO4_WPORT PORTC +#define AIO4_DDR DDRC + +#define AIO5_PIN PINC5 +#define AIO5_RPORT PINC +#define AIO5_WPORT PORTC +#define AIO5_DDR DDRC diff --git a/arduino_644.h b/arduino_644.h new file mode 100644 index 0000000..9debeda --- /dev/null +++ b/arduino_644.h @@ -0,0 +1,227 @@ +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define ICP1 DIO8 + +/* +pins +*/ + +#define DIO0_PIN PINB0 +#define DIO0_RPORT PINB +#define DIO0_WPORT PORTB +#define DIO0_DDR DDRB + +#define DIO1_PIN PINB1 +#define DIO1_RPORT PINB +#define DIO1_WPORT PORTB +#define DIO1_DDR DDRB + +#define DIO2_PIN PINB2 +#define DIO2_RPORT PINB +#define DIO2_WPORT PORTB +#define DIO2_DDR DDRB + +#define DIO3_PIN PINB3 +#define DIO3_RPORT PINB +#define DIO3_WPORT PORTB +#define DIO3_DDR DDRB + +#define DIO4_PIN PINB4 +#define DIO4_RPORT PINB +#define DIO4_WPORT PORTB +#define DIO4_DDR DDRB + +#define DIO5_PIN PINB5 +#define DIO5_RPORT PINB +#define DIO5_WPORT PORTB +#define DIO5_DDR DDRB + +#define DIO6_PIN PINB6 +#define DIO6_RPORT PINB +#define DIO6_WPORT PORTB +#define DIO6_DDR DDRB + +#define DIO7_PIN PINB7 +#define DIO7_RPORT PINB +#define DIO7_WPORT PORTB +#define DIO7_DDR DDRB + +#define DIO8_PIN PIND0 +#define DIO8_RPORT PIND +#define DIO8_WPORT PORTD +#define DIO8_DDR DDRD + +#define DIO9_PIN PIND1 +#define DIO9_RPORT PIND +#define DIO9_WPORT PORTD +#define DIO9_DDR DDRD + +#define DIO10_PIN PIND2 +#define DIO10_RPORT PIND +#define DIO10_WPORT PORTD +#define DIO10_DDR DDRD + +#define DIO11_PIN PIND3 +#define DIO11_RPORT PIND +#define DIO11_WPORT PORTD +#define DIO11_DDR DDRD + +#define DIO12_PIN PIND4 +#define DIO12_RPORT PIND +#define DIO12_WPORT PORTD +#define DIO12_DDR DDRD + +#define DIO13_PIN PIND5 +#define DIO13_RPORT PIND +#define DIO13_WPORT PORTD +#define DIO13_DDR DDRD + +#define DIO14_PIN PIND6 +#define DIO14_RPORT PIND +#define DIO14_WPORT PORTD +#define DIO14_DDR DDRD + +#define DIO15_PIN PIND7 +#define DIO15_RPORT PIND +#define DIO15_WPORT PORTD +#define DIO15_DDR DDRD + +#define DIO16_PIN PINC0 +#define DIO16_RPORT PINC +#define DIO16_WPORT PORTC +#define DIO16_DDR DDRC + +#define DIO17_PIN PINC1 +#define DIO17_RPORT PINC +#define DIO17_WPORT PORTC +#define DIO17_DDR DDRC + +#define DIO18_PIN PINC2 +#define DIO18_RPORT PINC +#define DIO18_WPORT PORTC +#define DIO18_DDR DDRC + +#define DIO19_PIN PINC3 +#define DIO19_RPORT PINC +#define DIO19_WPORT PORTC +#define DIO19_DDR DDRC + +#define DIO20_PIN PINC4 +#define DIO20_RPORT PINC +#define DIO20_WPORT PORTC +#define DIO20_DDR DDRC + +#define DIO21_PIN PINC5 +#define DIO21_RPORT PINC +#define DIO21_WPORT PORTC +#define DIO21_DDR DDRC + +#define DIO22_PIN PINC6 +#define DIO22_RPORT PINC +#define DIO22_WPORT PORTC +#define DIO22_DDR DDRC + +#define DIO23_PIN PINC7 +#define DIO23_RPORT PINC +#define DIO23_WPORT PORTC +#define DIO23_DDR DDRC + +#define DIO24_PIN PINA7 +#define DIO24_RPORT PINA +#define DIO24_WPORT PORTA +#define DIO24_DDR DDRA + +#define DIO25_PIN PINA6 +#define DIO25_RPORT PINA +#define DIO25_WPORT PORTA +#define DIO25_DDR DDRA + +#define DIO26_PIN PINA5 +#define DIO26_RPORT PINA +#define DIO26_WPORT PORTA +#define DIO26_DDR DDRA + +#define DIO27_PIN PINA4 +#define DIO27_RPORT PINA +#define DIO27_WPORT PORTA +#define DIO27_DDR DDRA + +#define DIO28_PIN PINA3 +#define DIO28_RPORT PINA +#define DIO28_WPORT PORTA +#define DIO28_DDR DDRA + +#define DIO29_PIN PINA2 +#define DIO29_RPORT PINA +#define DIO29_WPORT PORTA +#define DIO29_DDR DDRA + +#define DIO30_PIN PINA1 +#define DIO30_RPORT PINA +#define DIO30_WPORT PORTA +#define DIO30_DDR DDRA + +#define DIO31_PIN PINA0 +#define DIO31_RPORT PINA +#define DIO31_WPORT PORTA +#define DIO31_DDR DDRA + +#define AIO0_PIN PINA0 +#define AIO0_RPORT PINA +#define AIO0_WPORT PORTA +#define AIO0_DDR DDRA + +#define AIO1_PIN PINA1 +#define AIO1_RPORT PINA +#define AIO1_WPORT PORTA +#define AIO1_DDR DDRA + +#define AIO2_PIN PINA2 +#define AIO2_RPORT PINA +#define AIO2_WPORT PORTA +#define AIO2_DDR DDRA + +#define AIO3_PIN PINA3 +#define AIO3_RPORT PINA +#define AIO3_WPORT PORTA +#define AIO3_DDR DDRA + +#define AIO4_PIN PINA4 +#define AIO4_RPORT PINA +#define AIO4_WPORT PORTA +#define AIO4_DDR DDRA + +#define AIO5_PIN PINA5 +#define AIO5_RPORT PINA +#define AIO5_WPORT PORTA +#define AIO5_DDR DDRA + +#define AIO6_PIN PINA6 +#define AIO6_RPORT PINA +#define AIO6_WPORT PORTA +#define AIO6_DDR DDRA + +#define AIO7_PIN PINA7 +#define AIO7_RPORT PINA +#define AIO7_WPORT PORTA +#define AIO7_DDR DDRA From 549e60e69d768141a60698187690c6038c5f80f4 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 18 Oct 2010 18:43:03 +1100 Subject: [PATCH 07/82] add flush queue for emergency stop --- dda_queue.c | 15 +++++++++++++++ dda_queue.h | 3 +++ gcode_process.c | 1 + 3 files changed, 19 insertions(+) diff --git a/dda_queue.c b/dda_queue.c index 71e3c3a..fb3edb2 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -106,3 +106,18 @@ void print_queue() { serial_writechar('E'); serial_writechar('\n'); } + +void queue_flush() { + // save interrupt flag + uint8_t sreg = SREG; + + // disable interrupts + cli(); + + // flush queue + mb_tail = mb_head; + movebuffer[mb_head].live = 0; + + // restore interrupt flag + SREG = sreg; +} diff --git a/dda_queue.h b/dda_queue.h index 9edf865..46b4a4f 100644 --- a/dda_queue.h +++ b/dda_queue.h @@ -33,4 +33,7 @@ void next_move(void) __attribute__ ((hot)); // print queue status void print_queue(void); +// flush the queue for eg; emergency stop +void queue_flush(void); + #endif /* _DDA_QUEUE */ diff --git a/gcode_process.c b/gcode_process.c index 2ced51b..789fd12 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -249,6 +249,7 @@ void process_gcode_command() { // M112- immediate stop case 112: disableTimerInterrupt(); + queue_flush(); power_off(); break; // M113- extruder PWM From b9073af737729fe1642148a5a3056a947427c300 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 19 Oct 2010 10:39:53 +1100 Subject: [PATCH 08/82] reduce analog subsystem use of interrupts --- analog.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/analog.c b/analog.c index 0fb0e8f..9ae7b59 100644 --- a/analog.c +++ b/analog.c @@ -42,6 +42,9 @@ ISR(ADC_vect) { if (adc_counter == 8) { adc_counter = 0; adc_running_mask = 1; + + // relax interrupt use for analog subsystem- stop after last analog read + ADCSRA &= ~MASK(ADIE); } } while ((adc_running_mask & ANALOG_MASK) == 0); @@ -61,5 +64,9 @@ uint16_t analog_read(uint8_t channel) { r = adc_result[channel]; // restore interrupt flag SREG = sreg; + + // re-enable analog read loop so we can get new values + ADCSRA |= MASK(ADIE); + return r; } From ea3aedd2a732412c0f44a80659396b17af3483cf Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 25 Oct 2010 22:50:57 +1100 Subject: [PATCH 09/82] add support for M115- capabilities string --- gcode_process.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index 789fd12..487bc1d 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -255,9 +255,13 @@ void process_gcode_command() { // M113- extruder PWM // M114- report XYZEF to host case 114: - sersendf_P("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n", current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); + sersendf_P(PSTR("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); break; - + // M115- capabilities string + case 115: + serial_writestr_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 HEATER_COUNT:1\n")); + break; + #ifdef HEATER_PIN // M130- heater P factor case 130: From c5e544b1fefa2cbd71c15891f2f4c29385491746 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 21 Oct 2010 21:44:28 +1100 Subject: [PATCH 10/82] prepare for protocol changes ie responses after ok instead of separate line --- gcode_parse.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index dd6ace8..53e0de1 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -7,6 +7,7 @@ #include "dda_queue.h" #include "debug.h" #include "heater.h" +#include "sersendf.h" #include "gcode_process.h" @@ -352,24 +353,21 @@ void gcode_parse_char(uint8_t c) { #endif ) { // process + serial_writestr_P(PSTR("ok ")); process_gcode_command(); - serial_writestr_P(PSTR("ok\n")); + serial_writestr_P(PSTR("\n")); // expect next line number if (next_target.seen_N == 1) next_target.N_expected = next_target.N + 1; } else { - serial_writestr_P(PSTR("Expected checksum ")); - serwrite_uint8(next_target.checksum_calculated); - serial_writechar('\n'); + sersendf_P(PSTR("rs %ld Expected checksum %d\n"), next_target.N_expected, next_target.checksum_calculated); request_resend(); } } else { - serial_writestr_P(PSTR("Expected line number ")); - serwrite_uint32(next_target.N_expected); - serial_writechar('\n'); + sersendf_P(PSTR("rs %ld Expected line number %ld\n"), next_target.N_expected, next_target.N_expected); request_resend(); } From d93dcff37872c22c1cc318523c14d0233cc20743 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 25 Oct 2010 22:45:22 +1100 Subject: [PATCH 11/82] merge multi_temp stuff --- config.h.dist | 59 +++++++++ gcode_process.c | 18 ++- heater.c | 164 +++++++++++++++--------- heater.h | 38 ++---- mendel.c | 6 + temp.c | 333 ++++++++++++++++++++++++------------------------ temp.h | 56 ++------ 7 files changed, 361 insertions(+), 313 deletions(-) diff --git a/config.h.dist b/config.h.dist index e1d0c55..20db5c0 100644 --- a/config.h.dist +++ b/config.h.dist @@ -71,6 +71,63 @@ #define TEMP_THERMISTOR // #define TEMP_AD595 +#define NUM_TEMP_SENSORS 1 +#ifdef TEMP_C +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* If your temperature sensor has no associated heater, enter '255' as the * +* heater index. * +* * +\***************************************************************************/ + +struct { + uint8_t temp_type; + uint8_t temp_pin; + + uint8_t heater_index; +} temp_sensors[NUM_TEMP_SENSORS] = +{ + { + TT_MAX6675, + 0, + 0 + } +}; +#endif + +#define NUM_HEATERS 1 +#ifdef HEATER_C +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* For the atmega168/328, timer/pin mappings are as follows * +* * +* OCR0A - PD6 * +* OCR0B - PD5 * +* OCR2A - PB3 * +* OCR2B - PD3 * +* * +\***************************************************************************/ +struct { + volatile uint8_t *heater_port; + uint8_t heater_pin; + volatile uint8_t *heater_pwm; +} heaters[NUM_HEATERS] = +{ + { + &PORTD, + PIND0, + &OCR0A + } +}; +#endif + +// temperature history count. higher values make PID derivative term more stable at the expense of reaction time +#define TH_COUNT 8 + // if you selected thermistor or AD595, what pin is it on? #define TEMP_PIN_CHANNEL AIO0_PIN #define ANALOG_MASK MASK(TEMP_PIN_CHANNEL) @@ -224,6 +281,8 @@ #define FAN_PIN DIO5 #define FAN_PWM OCR0B +#define PID_SCALE 1024L + // -------------------------------------------------------------------------- // you shouldn't need to edit anything below this line diff --git a/gcode_process.c b/gcode_process.c index 487bc1d..9a31d4c 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -197,7 +197,7 @@ void process_gcode_command() { // M104- set temperature case 104: - temp_set(next_target.S); + temp_set(next_target.P, next_target.S); if (next_target.S) { enable_heater(); power_on(); @@ -209,7 +209,7 @@ void process_gcode_command() { // M105- get temperature case 105: - temp_print(); + temp_print(next_target.P); break; // M106- fan on @@ -225,7 +225,7 @@ void process_gcode_command() { // M109- set temp and wait case 109: - temp_set(next_target.S); + temp_set(next_target.P, next_target.S); if (next_target.S) { enable_heater(); power_on(); @@ -266,22 +266,26 @@ void process_gcode_command() { // M130- heater P factor case 130: if (next_target.seen_S) - p_factor = next_target.S; +// p_factor = next_target.S; + pid_set_p(next_target.P, next_target.S); break; // M131- heater I factor case 131: if (next_target.seen_S) - i_factor = next_target.S; +// i_factor = next_target.S; + pid_set_i(next_target.P, next_target.S); break; // M132- heater D factor case 132: if (next_target.seen_S) - d_factor = next_target.S; +// d_factor = next_target.S; + pid_set_d(next_target.P, next_target.S); break; // M133- heater I limit case 133: if (next_target.seen_S) - i_limit = next_target.S; +// i_limit = next_target.S; + pid_set_i_limit(next_target.P, next_target.S); break; // M134- save PID settings to eeprom case 134: diff --git a/heater.c b/heater.c index 320d3c9..259662c 100644 --- a/heater.c +++ b/heater.c @@ -1,107 +1,149 @@ #include "heater.h" -#ifdef HEATER_PIN - #include +#include -#include "sersendf.h" +#include "arduino.h" +#include "timer.h" #include "debug.h" +#include "sersendf.h" -int16_t heater_p = 0; -int16_t heater_i = 0; -int16_t heater_d = 0; +#define HEATER_C +#include "config.h" + +// this struct holds the heater PID factors that are stored in the EEPROM during poweroff +struct { + int32_t p_factor; + int32_t i_factor; + int32_t d_factor; + int16_t i_limit; +} heaters_pid[NUM_HEATERS]; + +// this struct holds the runtime heater data- PID counters and such +struct { + int16_t heater_p; + int16_t heater_i; + int16_t heater_d; + + uint8_t pid_output; + + uint16_t temp_history[TH_COUNT]; + uint8_t temp_history_pointer; +} heaters_runtime[NUM_HEATERS]; #define DEFAULT_P 8192 #define DEFAULT_I 512 #define DEFAULT_D -24576 #define DEFAULT_I_LIMIT 384 -int32_t p_factor = 0; -int32_t i_factor = 0; -int32_t d_factor = 0; -int16_t i_limit = 0; +// this lives in the eeprom so we can save our PID settings for each heater +typedef struct { + int32_t EE_p_factor; + int32_t EE_i_factor; + int32_t EE_d_factor; + int16_t EE_i_limit; +} EE_factor; -int32_t EEMEM EE_p_factor; -int32_t EEMEM EE_i_factor; -int32_t EEMEM EE_d_factor; -int16_t EEMEM EE_i_limit; - -#define TH_COUNT 8 -uint16_t temp_history[TH_COUNT] __attribute__ ((__section__ (".bss"))); -uint8_t th_p = 0; +EE_factor EEMEM EE_factors[NUM_HEATERS]; void heater_init() { - p_factor = eeprom_read_dword((uint32_t *) &EE_p_factor); - i_factor = eeprom_read_dword((uint32_t *) &EE_i_factor); - d_factor = eeprom_read_dword((uint32_t *) &EE_d_factor); - i_limit = eeprom_read_word((uint16_t *) &EE_i_limit); - - if ((p_factor == 0) && (i_factor == 0) && (d_factor == 0) && (i_limit == 0)) { - p_factor = DEFAULT_P; - i_factor = DEFAULT_I; - d_factor = DEFAULT_D; - i_limit = DEFAULT_I_LIMIT; + // read factors from eeprom + uint8_t i; + for (i = 0; i < NUM_HEATERS; i++) { + heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor); + heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor); + heaters_pid[i].d_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_d_factor); + heaters_pid[i].i_limit = eeprom_read_word((uint16_t *) &EE_factors[i].EE_i_limit); + + if ((heaters_pid[i].p_factor == 0) && (heaters_pid[i].i_factor == 0) && (heaters_pid[i].d_factor == 0) && (heaters_pid[i].i_limit == 0)) { + heaters_pid[i].p_factor = DEFAULT_P; + heaters_pid[i].i_factor = DEFAULT_I; + heaters_pid[i].d_factor = DEFAULT_D; + heaters_pid[i].i_limit = DEFAULT_I_LIMIT; + } } } void heater_save_settings() { - eeprom_write_dword((uint32_t *) &EE_p_factor, p_factor); - eeprom_write_dword((uint32_t *) &EE_i_factor, i_factor); - eeprom_write_dword((uint32_t *) &EE_d_factor, d_factor); - eeprom_write_word((uint16_t *) &EE_i_limit, i_limit); + uint8_t i; + for (i = 0; i < NUM_HEATERS; i++) { + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_p_factor, heaters_pid[i].p_factor); + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_i_factor, heaters_pid[i].i_factor); + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_d_factor, heaters_pid[i].d_factor); + eeprom_write_word((uint16_t *) &EE_factors[i].EE_i_limit, heaters_pid[i].i_limit); + } } -void heater_tick(int16_t current_temp, int16_t target_temp) { +void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { + // now for heater stuff int16_t t_error = target_temp - current_temp; - temp_history[th_p++] = current_temp; - th_p &= (TH_COUNT - 1); + heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp; + heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1); // PID stuff // proportional - heater_p = t_error; + heaters_runtime[h].heater_p = t_error; // integral - heater_i += t_error; + heaters_runtime[h].heater_i += t_error; // prevent integrator wind-up - if (heater_i > i_limit) - heater_i = i_limit; - else if (heater_i < -i_limit) - heater_i = -i_limit; + if (heaters_runtime[h].heater_i > heaters_pid[h].i_limit) + heaters_runtime[h].heater_i = heaters_pid[h].i_limit; + else if (heaters_runtime[h].heater_i < -heaters_pid[h].i_limit) + heaters_runtime[h].heater_i = -heaters_pid[h].i_limit; // derivative // note: D follows temp rather than error so there's no large derivative when the target changes - heater_d = current_temp - temp_history[th_p]; + heaters_runtime[h].heater_d = current_temp - heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer]; // combine factors int32_t pid_output_intermed = ( - ( - (((int32_t) heater_p) * p_factor) + - (((int32_t) heater_i) * i_factor) + - (((int32_t) heater_d) * d_factor) - ) / PID_SCALE + ( + (((int32_t) heaters_runtime[h].heater_p) * heaters_pid[h].p_factor) + + (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + + (((int32_t) heaters_runtime[h].heater_d) * heaters_pid[h].d_factor) + ) / PID_SCALE ); // rebase and limit factors - uint8_t pid_output; if (pid_output_intermed > 255) - pid_output = 255; + heaters_runtime[h].pid_output = 255; else if (pid_output_intermed < 0) - pid_output = 0; + heaters_runtime[h].pid_output = 0; else - pid_output = pid_output_intermed & 0xFF; + heaters_runtime[h].pid_output = pid_output_intermed & 0xFF; if (debug_flags & DEBUG_PID) - sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heater_p, p_factor, (int32_t) heater_p * p_factor / PID_SCALE, heater_i, i_factor, (int32_t) heater_i * i_factor / PID_SCALE, heater_d, d_factor, (int32_t) heater_d * d_factor / PID_SCALE, pid_output_intermed, pid_output); + sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heaters_runtime[h].heater_p, heaters_pid[h].p_factor, (int32_t) heaters_runtime[h].heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heaters_runtime[h].heater_d, heaters_pid[h].d_factor, (int32_t) heaters_runtime[h].heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, heaters_runtime[h].pid_output); - #ifdef HEATER_PWM - HEATER_PWM = pid_output; - #else - if (pid_output >= 8) - enable_heater(); - else - disable_heater(); - #endif + heater_set(h, heaters_runtime[h].pid_output); } -#endif /* HEATER_PIN */ \ No newline at end of file +void heater_set(uint8_t index, uint8_t value) { + if (heaters[index].heater_pwm) { + *heaters[index].heater_pwm = value; + } + else { + if (value >= 8) + *heaters[index].heater_port |= MASK(heaters[index].heater_pin); + else + *heaters[index].heater_port &= ~MASK(heaters[index].heater_pin); + } +} + +void pid_set_p(uint8_t index, int32_t p) { + heaters_pid[index].p_factor = p; +} + +void pid_set_i(uint8_t index, int32_t i) { + heaters_pid[index].i_factor = i; +} + +void pid_set_d(uint8_t index, int32_t d) { + heaters_pid[index].d_factor = d; +} + +void pid_set_i_limit(uint8_t index, int32_t i_limit) { + heaters_pid[index].i_limit = i_limit; +} diff --git a/heater.h b/heater.h index 1e1a201..fdc9dc9 100644 --- a/heater.h +++ b/heater.h @@ -1,40 +1,20 @@ #ifndef _HEATER_H #define _HEATER_H -#include "config.h" +#include -#ifdef HEATER_PIN - -#ifdef HEATER_PWM - #define enable_heater() do { TCCR0A |= MASK(COM0A1); } while (0) - #define disable_heater() do { TCCR0A &= ~MASK(COM0A1); } while (0) -#else - #define enable_heater() WRITE(HEATER_PIN, 1) - #define disable_heater() WRITE(HEATER_PIN, 0) -#endif - -// extruder heater PID factors -// google "PID without a PHD" if you don't understand this PID stuff -extern int32_t p_factor; -extern int32_t i_factor; -extern int32_t d_factor; -extern int16_t i_limit; - -#define PID_SCALE 1024L -#define I_LIMIT 4000 +#define enable_heater() heater_set(0, 64) +#define disable_heater() heater_set(0, 0) void heater_init(void); void heater_save_settings(void); -void heater_tick(int16_t current_temp, int16_t target_temp); -#else /* HEATER_PIN */ +void heater_set(uint8_t index, uint8_t value); +void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp); -// if there is no heater pin, there is no heater -#define enable_heater() /* empty */ -#define disable_heater() /* empty */ -#define heater_init() /* empty */ -#define heater_save_settings() /* empty */ -#define heater_tick(p1, p2) /* empty */ +void pid_set_p(uint8_t index, int32_t p); +void pid_set_i(uint8_t index, int32_t i); +void pid_set_d(uint8_t index, int32_t d); +void pid_set_i_limit(uint8_t index, int32_t i_limit); -#endif /* HEATER_PIN */ #endif /* _HEATER_H */ diff --git a/mendel.c b/mendel.c index 5783dcb..ee9aeda 100644 --- a/mendel.c +++ b/mendel.c @@ -62,6 +62,12 @@ void io_init(void) { TIMSK0 = 0; OCR0A = 0; OCR0B = 255; + + TCCR2A = MASK(WGM21) | MASK(WGM20); + TCCR2B = MASK(CS20); + TIMSK2 = 0; + OCR2A = 0; + OCR2B = 0; #endif #ifdef STEPPER_ENABLE_PIN diff --git a/temp.c b/temp.c index 7e818c7..a662304 100644 --- a/temp.c +++ b/temp.c @@ -1,34 +1,41 @@ -/* - temp.c - - This file currently reads temp from a MAX6675 on the SPI bus. - - temp fields are 14.2 fixed point, so temp_set(500) will set the temperature to 125 celsius, and temp_get() = 600 is reporting a temperature of 150 celsius. - - the conversion to/from this unit is done in gcode.c, near: - if (next_target.M == 104) - next_target.S = decfloat_to_int(&read_digit, 4, 1); - and - // M105- get temperature - case 105: - uint16_t t = temp_get(); - - note that the MAX6675 can't do more than approx 5 conversions per second- we go for 4 so the timing isn't too tight -*/ - -#include "temp.h" +#include "temp.h" +#include #include +#include -#include "clock.h" -#include "serial.h" -#include "sermsg.h" +#include "arduino.h" #include "timer.h" -#include "dda.h" -#include "sersendf.h" #include "debug.h" +#include "sersendf.h" #include "heater.h" +typedef enum { + TT_THERMISTOR, + TT_MAX6675, + TT_AD595 +} temp_types; + +typedef enum { + PRESENT, + TCOPEN +} temp_flags_enum; + +#define TEMP_C +#include "config.h" + +// this struct holds the runtime sensor data- read temperatures, targets, etc +struct { + temp_flags_enum temp_flags; + + uint16_t last_read_temp; + uint16_t target_temp; + + uint8_t temp_residency; + + uint16_t next_read_time; +} temp_sensors_runtime[NUM_TEMP_SENSORS]; + #ifdef TEMP_MAX6675 #endif @@ -64,157 +71,143 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = { #include "analog.h" #endif -#ifndef TEMP_MAX6675 - #ifndef TEMP_THERMISTOR - #ifndef TEMP_AD595 - #error none of TEMP_MAX6675, TEMP_THERMISTOR or TEMP_AD595 are defined! What type of temp sensor are you using? - #endif - #endif -#endif - -uint16_t current_temp = 0; -uint16_t target_temp = 0; - -uint8_t temp_flags = 0; -uint8_t temp_residency = 0; - -#ifndef ABSDELTA -#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a))) -#endif - -uint16_t temp_read() { - uint16_t temp; - -#ifdef TEMP_MAX6675 - #ifdef PRR - PRR &= ~MASK(PRSPI); - #elif defined PRR0 - PRR0 &= ~MASK(PRSPI); - #endif - - SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0); - - // enable MAX6675 - WRITE(SS, 0); - - // ensure 100ns delay - a bit extra is fine - delay(1); - - // read MSB - SPDR = 0; - for (;(SPSR & MASK(SPIF)) == 0;); - temp = SPDR; - temp <<= 8; - - // read LSB - SPDR = 0; - for (;(SPSR & MASK(SPIF)) == 0;); - temp |= SPDR; - - // disable MAX6675 - WRITE(SS, 1); - - temp_flags = 0; - if ((temp & 0x8002) == 0) { - // got "device id" - temp_flags |= TEMP_FLAG_PRESENT; - if (temp & 4) { - // thermocouple open - temp_flags |= TEMP_FLAG_TCOPEN; +void temp_sensor_tick() { + uint8_t i = 0, all_within_range = 1; + for (; i < NUM_TEMP_SENSORS; i++) { + if (temp_sensors_runtime[i].next_read_time) { + temp_sensors_runtime[i].next_read_time--; } else { - current_temp = temp >> 3; - return current_temp; + uint16_t temp = 0; + #ifdef TEMP_THERMISTOR + uint8_t j; + #endif + //time to deal with this temp sensor + switch(temp_sensors[i].temp_type) { + #ifdef TEMP_MAX6675 + case TT_MAX6675: + #ifdef PRR + PRR &= ~MASK(PRSPI); + #elif defined PRR0 + PRR0 &= ~MASK(PRSPI); + #endif + + SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0); + + // enable TT_MAX6675 + WRITE(SS, 0); + + // ensure 100ns delay - a bit extra is fine + delay(1); + + // read MSB + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp = SPDR; + temp <<= 8; + + // read LSB + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp |= SPDR; + + // disable TT_MAX6675 + WRITE(SS, 1); + + temp_sensors_runtime[i].temp_flags = 0; + if ((temp & 0x8002) == 0) { + // got "device id" + temp_sensors_runtime[i].temp_flags |= PRESENT; + if (temp & 4) { + // thermocouple open + temp_sensors_runtime[i].temp_flags |= TCOPEN; + } + else { + temp = temp >> 3; + } + } + + // FIXME: placeholder number + temp_sensors_runtime[i].next_read_time = 25; + + break; + #endif /* TEMP_MAX6675 */ + + #ifdef TEMP_THERMISTOR + case TT_THERMISTOR: + + //Read current temperature + temp = analog_read(temp_sensors[i].temp_pin); + + //Calculate real temperature based on lookup table + for (j = 1; j < NUMTEMPS; j++) { + if (pgm_read_word(&(temptable[j][0])) > temp) { + // multiply by 4 because internal temp is stored as 14.2 fixed point + temp = pgm_read_word(&(temptable[j][1])) + (pgm_read_word(&(temptable[j][0])) - temp) * 4 * (pgm_read_word(&(temptable[j-1][1])) - pgm_read_word(&(temptable[j][1]))) / (pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0]))); + break; + } + } + + //Clamp for overflows + if (j == NUMTEMPS) + temp = temptable[NUMTEMPS-1][1]; + + // FIXME: placeholder number + temp_sensors_runtime[i].next_read_time = 0; + + break; + #endif /* TEMP_THERMISTOR */ + + #ifdef TEMP_AD595 + case TT_AD595: + temp = analog_read(temp_pin); + + // convert + // >>8 instead of >>10 because internal temp is stored as 14.2 fixed point + temp = (temp * 500L) >> 8; + + // FIXME: placeholder number + temp_sensors[i].next_read_time = 0; + + break; + #endif /* TEMP_AD595 */ + } + temp_sensors_runtime[i].last_read_temp = temp; + + if (labs(temp - temp_sensors_runtime[i].target_temp) < TEMP_HYSTERESIS) { + if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME) + temp_sensors_runtime[i].temp_residency++; + } + else { + temp_sensors_runtime[i].temp_residency = 0; + all_within_range = 0; + } + + if (temp_sensors[i].heater_index != 255) { + heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp); + } } } -#endif /* TEMP_MAX6675 */ - -#ifdef TEMP_THERMISTOR - uint8_t i; - - //Read current temperature - temp = analog_read(TEMP_PIN_CHANNEL); - - //Calculate real temperature based on lookup table - for (i = 1; i < NUMTEMPS; i++) { - if (pgm_read_word(&(temptable[i][0])) > temp) { - // multiply by 4 because internal temp is stored as 14.2 fixed point - temp = pgm_read_word(&(temptable[i][1])) + (pgm_read_word(&(temptable[i][0])) - temp) * 4 * (pgm_read_word(&(temptable[i-1][1])) - pgm_read_word(&(temptable[i][1]))) / (pgm_read_word(&(temptable[i][0])) - pgm_read_word(&(temptable[i-1][0]))); - break; - } - } - - //Clamp for overflows - if (i == NUMTEMPS) - temp = temptable[NUMTEMPS-1][1]; - - return temp; - -#endif /* TEMP_THERMISTOR */ - -#ifdef TEMP_AD595 - temp = analog_read(TEMP_PIN_CHANNEL); - - // convert - // >>8 instead of >>10 because internal temp is stored as 14.2 fixed point - temp = (temp * 500L) >> 8; - - return temp; -#endif /* TEMP_AD595 */ - - return 0; -} - -void temp_set(uint16_t t) { - if (t) { - steptimeout = 0; - power_on(); - } - target_temp = t; -} - -uint16_t temp_get() { - return current_temp; -} - -uint16_t temp_get_target() { - return target_temp; -} - -void temp_print() { - if (temp_flags & TEMP_FLAG_TCOPEN) { - serial_writestr_P(PSTR("T: no thermocouple!\n")); - } - else { - uint8_t c = 0, t = 0; - - c = (current_temp & 3) * 25; - t = (target_temp & 3) * 25; - #ifdef REPRAP_HOST_COMPATIBILITY - sersendf_P(PSTR(" T: %u.%u\n"), current_temp >> 2, c); - #else - sersendf_P(PSTR("T: %u.%u/%u.%u :%u\n"), current_temp >> 2, c, target_temp >> 2, t, temp_residency); - #endif - } -} - -void temp_tick() { - if (target_temp) { - steptimeout = 0; - - temp_read(); - - heater_tick(current_temp, target_temp); - - if (ABSDELTA(current_temp, target_temp) > TEMP_HYSTERESIS) - temp_residency = 0; - else if (temp_residency < TEMP_RESIDENCY_TIME) - temp_residency++; - } } uint8_t temp_achieved() { - if (temp_residency >= TEMP_RESIDENCY_TIME) - return 255; - return 0; + uint8_t i, all_ok = 255; + for (i = 0; i < NUM_TEMP_SENSORS; i++) { + if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME) + all_ok = 0; + } + return all_ok; +} + +void temp_set(uint8_t index, uint16_t temperature) { + temp_sensors_runtime[index].target_temp = temperature; + temp_sensors_runtime[index].temp_residency = 0; +} + +void temp_print(uint8_t index) { + uint8_t c = 0; + + c = (temp_sensors_runtime[index].last_read_temp & 3) * 25; + + sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c); } diff --git a/temp.h b/temp.h index 9955a9e..5555b8e 100644 --- a/temp.h +++ b/temp.h @@ -3,59 +3,23 @@ #include -#include "config.h" +/* +NOTES -#define TEMP_FLAG_PRESENT 1 -#define TEMP_FLAG_TCOPEN 2 +no point in specifying a port- all the different temp sensors we have must be on a particular port. The MAX6675 must be on the SPI, and the thermistor and AD595 must be on an analog port. -#ifdef TEMP_MAX6675 -typedef union { - struct { - uint8_t high; - uint8_t low; - } buf; - struct { - uint16_t dummy :1; - uint16_t reading :12; - uint16_t tc_open :1; - uint16_t device_id :1; - uint16_t tristate :1; - } interpret; -} max6675_data_format; -#endif +we still need to specify which analog pins we use in machine.h for the analog sensors however, otherwise the analog subsystem won't read them. +*/ -#ifdef TEMP_THERMISTOR -#include -#endif +#define temp_tick temp_sensor_tick -#ifdef TEMP_AD595 -#endif +void temp_sensor_tick(void); -// setup temperature system -void temp_init(void); - -// save PID factors to EEPROM -void temp_save_settings(void); - -// read temperature from sensor -uint16_t temp_read(void); - -// set target temperature -void temp_set(uint16_t t); - -// return last read temperature -uint16_t temp_get(void); - -// return target temperature -uint16_t temp_get_target(void); - -// true if last read temp is close to target temp, false otherwise uint8_t temp_achieved(void); -// send current temperature to host -void temp_print(void); +void temp_set(uint8_t index, uint16_t temperature); +void temp_print(uint8_t index); -// periodically read temperature and update heater with PID -void temp_tick(void); +uint16_t temp_read(uint8_t index); #endif /* _TIMER_H */ From c7ac215c5903d409f9a9e69644a011d995dd9ea3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 25 Oct 2010 23:14:31 +1100 Subject: [PATCH 12/82] merging unified_timer stuff --- Makefile | 2 +- clock.c | 74 -------------------- clock.h | 32 --------- dda.c | 1 - dda_queue.c | 15 ++--- delay.h | 2 + gcode_process.c | 2 +- mendel.c | 10 +-- timer.c | 176 +++++++++++++++++++++++++----------------------- timer.h | 23 ++++--- 10 files changed, 116 insertions(+), 221 deletions(-) delete mode 100644 clock.c delete mode 100644 clock.h diff --git a/Makefile b/Makefile index f28534d..a68da2f 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c clock.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c ############################################################################## # # diff --git a/clock.c b/clock.c deleted file mode 100644 index 9056814..0000000 --- a/clock.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - clock.c - - a system clock with 1ms ticks -*/ - -#include "clock.h" - -#include -#include - -#include "config.h" - -// global clock -#ifdef GLOBAL_CLOCK -volatile uint32_t clock = 0; -#endif - -// 1/4 second tick -uint8_t clock_counter_250ms = 0; -uint8_t clock_counter_1s = 0; -volatile uint8_t clock_flag = 0; - -void clock_setup() { - // use system clock - ASSR = 0; - - // no compare match, CTC mode - TCCR2A = MASK(WGM21); - // TODO: Timer 2 has higher priority than Timer 1 used for the stepper - // interrupts, which is bad. See AVR Reference Manual p. 9: - // "The interrupts have priority in accordance - // with their Interrupt Vector position. The - // lower the Interrupt Vector address, the higher - // the priority." - // in conjunction with p. 63 (interrupt vector table). - - // 128 prescaler (16MHz / 128 = 125KHz) - TCCR2B = MASK(CS22) | MASK(CS20); - - // 125KHz / 125 = 1KHz for a 1ms tick rate - OCR2A = 125; - - // interrupt on overflow, when counter reaches OCR2A - TIMSK2 |= MASK(OCIE2A); -} - -ISR(TIMER2_COMPA_vect) { - // global clock -#ifdef GLOBAL_CLOCK - clock++; -#endif - // 1/4 second tick - if (++clock_counter_250ms == 250) { - clock_flag |= CLOCK_FLAG_250MS; - clock_counter_250ms = 0; - if (++clock_counter_1s == 4) { - clock_flag |= CLOCK_FLAG_1S; - clock_counter_1s = 0; - } - } -} - -#ifdef GLOBAL_CLOCK -uint32_t clock_read() { - uint32_t c; - - cli(); // set atomic - c = clock; // copy clock value - sei(); // release atomic - - return c; -} -#endif diff --git a/clock.h b/clock.h deleted file mode 100644 index b8eabf0..0000000 --- a/clock.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _CLOCK_H -#define _CLOCK_H - -#include - -void clock_setup(void) __attribute__ ((cold)); - -#ifdef GLOBAL_CLOCK -uint32_t clock_read(void); -#endif - -extern volatile uint8_t clock_flag; - -#define CLOCK_FLAG_250MS 1 -#define CLOCK_FLAG_1S 2 - -/* - ifclock() {} - - so we can do stuff like: - ifclock(CLOCK_FLAG_250MS) { - report(); - } - - or: - ifclock(CLOCK_FLAG_1S) - power_off(); -*/ - -#define ifclock(F) for (;clock_flag & (F);clock_flag &= ~(F)) - -#endif /* _CLOCK_H */ diff --git a/dda.c b/dda.c index d079df4..44c2c1e 100644 --- a/dda.c +++ b/dda.c @@ -399,7 +399,6 @@ void dda_start(DDA *dda) { // set timeout for first step setTimer(dda->c >> 8); - enableTimerInterrupt(); } } diff --git a/dda_queue.c b/dda_queue.c index fb3edb2..d295c14 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -9,6 +9,7 @@ #include "sermsg.h" #include "temp.h" #include "delay.h" +#include "sersendf.h" uint8_t mb_head = 0; uint8_t mb_tail = 0; @@ -78,7 +79,7 @@ void enqueue(TARGET *t) { mb_head = h; // fire up in case we're not running yet - if (timerInterruptIsEnabled() == 0) + if (movebuffer[mb_tail].live == 0) next_move(); } @@ -92,19 +93,11 @@ void next_move() { mb_tail = t; } else - disableTimerInterrupt(); + setTimer(0); } void print_queue() { - serial_writechar('Q'); - serwrite_uint8(mb_tail); - serial_writechar('/'); - serwrite_uint8(mb_head); - if (queue_full()) - serial_writechar('F'); - if (queue_empty()) - serial_writechar('E'); - serial_writechar('\n'); + sersendf_P(PSTR("Q%d/%d%c\n"), mb_tail, mb_head, (queue_full()?'F':(queue_empty()?'E':' '))); } void queue_flush() { diff --git a/delay.h b/delay.h index 16abe03..83aaf36 100644 --- a/delay.h +++ b/delay.h @@ -3,6 +3,8 @@ #include +#define WAITING_DELAY 10 MS + void delay(uint32_t delay); void delay_ms(uint32_t delay); diff --git a/gcode_process.c b/gcode_process.c index 9a31d4c..542d064 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -248,7 +248,7 @@ void process_gcode_command() { #endif // M112- immediate stop case 112: - disableTimerInterrupt(); + timer_stop(); queue_flush(); power_off(); break; diff --git a/mendel.c b/mendel.c index ee9aeda..08fb037 100644 --- a/mendel.c +++ b/mendel.c @@ -9,7 +9,6 @@ #include "dda.h" #include "gcode_parse.h" #include "timer.h" -#include "clock.h" #include "temp.h" #include "sermsg.h" #include "watchdog.h" @@ -93,10 +92,7 @@ void init(void) { io_init(); // set up timers - setupTimerInterrupt(); - - // set up clock - clock_setup(); + timer_init(); // read PID settings from EEPROM heater_init(); @@ -142,8 +138,8 @@ void clock_250ms(void) { print_queue(); } // temperature - if (temp_get_target()) - temp_print(); +/* if (temp_get_target()) + temp_print();*/ } } diff --git a/timer.c b/timer.c index 90a6118..2f4586f 100644 --- a/timer.c +++ b/timer.c @@ -3,102 +3,112 @@ #include #include "dda_queue.h" -#include "watchdog.h" + +volatile uint32_t next_step_time; + +uint8_t clock_counter_250ms = 0; +uint8_t clock_counter_1s = 0; +volatile uint8_t clock_flag = 0; + +// how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535) +#define TICK_TIME 2 MS + +// timer overflow, happens every TICK_TIME +ISR(TIMER1_CAPT_vect) { + /* + check if next step time will occur before next overflow + */ + if (next_step_time > TICK_TIME) + next_step_time -= TICK_TIME; + else { + if (next_step_time > 0) { + OCR1A = next_step_time & 0xFFFF; + TIMSK1 |= MASK(OCIE1A); + } + } + + /* + clock stuff + */ + clock_counter_250ms += (TICK_TIME / (F_CPU / 1000)); + if (clock_counter_250ms >= 250) { + clock_counter_250ms -= 250; + clock_flag |= CLOCK_FLAG_250MS; + clock_counter_1s += 1; + if (clock_counter_1s >= 4) { + clock_counter_1s -= 4; + clock_flag |= CLOCK_FLAG_1S; + } + } +} ISR(TIMER1_COMPA_vect) { + // led on WRITE(SCK, 1); - + + // disable this interrupt. if we set a new timeout, it will be re-enabled when appropriate + TIMSK1 &= ~MASK(OCIE1A); + + // ensure we don't interrupt again unless timer is reset + next_step_time = 0; + + /* + stepper tick + */ queue_step(); - + + // led off WRITE(SCK, 0); } -void setupTimerInterrupt() +void timer_init() { // no outputs TCCR1A = 0; - // CTC mode - TCCR1B = MASK(WGM12); - // no interrupts yet - TIMSK1 = 0; + // CTC mode- use ICR for top + TCCR1B = MASK(WGM13) | MASK(WGM12) | MASK(CS10); + // set timeout- first timeout is indeterminate, probably doesn't matter + ICR1 = TICK_TIME; + // overflow interrupt (uses input capture interrupt in CTC:ICR mode) + TIMSK1 = MASK(ICIE1); } -// the following are all from reprap project 5D firmware with some modification to reduce redundancy - -uint8_t getTimerResolution(const uint32_t delay) -{ - // these also represent frequency: 1000000 / delay / 2 = frequency in hz. - - // our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs (4 millisecond max)) - // range: 8Mhz max - 122hz min - if (delay <= 65535L) - return 1; - // our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs (32 millisecond max)) - // range:1Mhz max - 15.26hz min - else if (delay <= 524280L) - return 2; - // our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs (0.26 seconds max)) - // range: 125Khz max - 1.9hz min - else if (delay <= 4194240L) - return 3; - // our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs (1.04 seconds max)) - // range: 31.25Khz max - 0.475hz min - else if (delay <= 16776960L) - return 4; - // our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs (4.19 seconds max)) - // range: 7.812Khz max - 0.119hz min - //its really slow... hopefully we can just get by with super slow. - return 5; -} - -void setTimerResolution(uint8_t r) -{ - // assuming CS10,CS11,CS12 are adjacent bits in platform endian order, - TCCR1B = (TCCR1B & ~(MASK(CS12) | MASK(CS11) | MASK(CS10))) | (r << CS10); -} - -uint16_t getTimerCeiling(const uint32_t delay) -{ - // our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs) - if (delay <= 65535L) - return (delay & 0xffff); - // our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs) - else if (delay <= 524280L) - return ((delay >> 3) & 0xffff); - // our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs) - else if (delay <= 4194240L) - return ((delay >> 6) & 0xffff); - // our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs) - else if (delay <= 16776960L) - return ((delay >> 8) & 0xffff); - // our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs) - else if (delay <= 67107840L) - return ((delay >> 10) & 0xffff); - //its really slow... hopefully we can just get by with super slow. - else - return 65535; -} - - -// Depending on how much work the interrupt function has to do, this is -// pretty accurate between 10 us and 0.1 s. At fast speeds, the time -// taken in the interrupt function becomes significant, of course. - -// Note - it is up to the user to call enableTimerInterrupt() after a call -// to this function. - void setTimer(uint32_t delay) { - // delay is the delay between steps in IOclk ticks. - // - // we break it into 5 different resolutions based on the delay. - // then we set the resolution based on the size of the delay. - // we also then calculate the timer ceiling required. (ie what the counter counts to) - // the result is the timer counts up to the appropriate time and then fires an interrupt. + // save interrupt flag + uint8_t sreg = SREG; + // disable interrupts + cli(); - setTimerResolution(0); // stop timer - GTCCR = MASK(PSRSYNC); // reset prescaler - affects timer 0 too but since it's doing PWM, it's not using the prescaler - - setTimerCeiling(getTimerCeiling(delay)); // set timeout - setTimerResolution(getTimerResolution(delay)); // restart timer with proper prescaler + // re-enable clock interrupt in case we're recovering from emergency stop + TIMSK1 |= MASK(ICIE1); + + if (delay > 0) { + // mangle timer variables + next_step_time = delay + TCNT1; + if (delay <= 16) { + // force interrupt + // TODO: datasheet says force only doesn't work in CTC:COMPA mode, test if CTC:ICR mode allows force + TIMSK1 |= MASK(OCIE1A); + TCCR1C |= MASK(FOC1A); + next_step_time = 0; + } + else if (delay <= TICK_TIME) { + OCR1A = next_step_time & 0xFFFF; + TIMSK1 |= MASK(OCIE1A); + } + } + else { + next_step_time = 0; + } + + // restore interrupt flag + SREG = sreg; +} + +void timer_stop() { + // disable all interrupts + TIMSK1 = 0; + // reset timeout + next_step_time = 0; } diff --git a/timer.h b/timer.h index afb51f8..2626860 100644 --- a/timer.h +++ b/timer.h @@ -8,21 +8,22 @@ #define US * (F_CPU / 1000000) #define MS * (F_CPU / 1000) -// #define DEFAULT_TICK (100 US) -#define WAITING_DELAY (10 MS) +/* +clock stuff +*/ +extern volatile uint8_t clock_flag; -void setupTimerInterrupt(void) __attribute__ ((cold)); +#define CLOCK_FLAG_250MS 1 +#define CLOCK_FLAG_1S 2 +#define ifclock(F) for (;clock_flag & (F);clock_flag &= ~(F)) -uint8_t getTimerResolution(const uint32_t delay); -void setTimerResolution(uint8_t r); - -uint16_t getTimerCeiling(const uint32_t delay); -#define setTimerCeiling(c) OCR1A = c +/* +timer stuff +*/ +void timer_init(void) __attribute__ ((cold)); void setTimer(uint32_t delay); -#define enableTimerInterrupt() do { TIMSK1 |= (1< Date: Tue, 26 Oct 2010 01:01:46 +1100 Subject: [PATCH 13/82] merge gen3 stuff --- Makefile | 12 +- config.h.dist | 30 ++--- extruder/Makefile | 142 ++++++++++++++++++++++ extruder/README | 2 + extruder/analog.c | 1 + extruder/analog.h | 1 + extruder/arduino.h | 1 + extruder/arduino_168_328p.h | 1 + extruder/config.h.dist | 79 +++++++++++++ extruder/delay.c | 1 + extruder/delay.h | 1 + extruder/extruder.c | 229 ++++++++++++++++++++++++++++++++++++ extruder/intercom.c | 220 ++++++++++++++++++++++++++++++++++ extruder/intercom.h | 17 +++ extruder/watchdog.c | 1 + extruder/watchdog.h | 1 + gcode_parse.c | 2 - gcode_process.c | 13 +- heater.c | 15 ++- intercom.c | 1 + intercom.h | 1 + mendel.c | 47 ++++---- temp.c | 63 +++++++++- temp.h | 2 + timer.c | 24 ++-- timer.h | 5 +- 26 files changed, 843 insertions(+), 69 deletions(-) create mode 100644 extruder/Makefile create mode 100644 extruder/README create mode 120000 extruder/analog.c create mode 120000 extruder/analog.h create mode 120000 extruder/arduino.h create mode 120000 extruder/arduino_168_328p.h create mode 100644 extruder/config.h.dist create mode 120000 extruder/delay.c create mode 120000 extruder/delay.h create mode 100644 extruder/extruder.c create mode 100644 extruder/intercom.c create mode 100644 extruder/intercom.h create mode 120000 extruder/watchdog.c create mode 120000 extruder/watchdog.h create mode 120000 intercom.c create mode 120000 intercom.h diff --git a/Makefile b/Makefile index a68da2f..c5a2cb8 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c ############################################################################## # # @@ -68,10 +68,12 @@ OBJCOPY = $(ARCH)objcopy # enables reprap-style acceleration # # ACCELERATION_RAMPING # # enables start/stop ramping # +# GEN3 # +# build for standard reprap electronics instead of your custom rig # # # ############################################################################## -DEFS = -DF_CPU=$(F_CPU) +DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3 # DEFS += "-DDEBUG=1" OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once @@ -115,9 +117,9 @@ clean: size: $(PROGRAM).elf @echo " SIZE Atmega168 Atmega328p Atmega644" - @$(OBJDUMP) -h $^ | perl -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (14 * 1024), 14, $$a * 100 / (30 * 1024), 30, $$a * 100 / (63 * 1024), 63 }' - @$(OBJDUMP) -h $^ | perl -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (4 * 1024), 4 }' - @$(OBJDUMP) -h $^ | perl -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (2 * 1024), 2 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (14 * 1024)), 14, ceil($$a * 100 / (30 * 1024)), 30, ceil($$a * 100 / (63 * 1024)), 63 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (4 * 1024)), 4 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (2 * 1024)), 2 }' config.h: config.h.dist @echo "Please review config.h, as config.h.dist is more recent." diff --git a/config.h.dist b/config.h.dist index 20db5c0..b9cdcf8 100644 --- a/config.h.dist +++ b/config.h.dist @@ -46,14 +46,14 @@ Each movement starts at the speed of the previous command and accelerates or decelerates linearly to reach target speed at the end of the movement. Can also be set in Makefile */ -#define ACCELERATION_REPRAP +// #define ACCELERATION_REPRAP /* acceleration and deceleration ramping. Each movement starts at (almost) no speed, linearly accelerates to target speed and decelerates just in time to smoothly stop at the target. alternative to ACCELERATION_REPRAP Can also be set in Makefile */ -//#define ACCELERATION_RAMPING +#define ACCELERATION_RAMPING // how fast to accelerate when using ACCELERATION_RAMPING // smaller values give quicker acceleration @@ -68,7 +68,7 @@ // which temperature sensor are you using? // #define TEMP_MAX6675 -#define TEMP_THERMISTOR +// #define TEMP_THERMISTOR // #define TEMP_AD595 #define NUM_TEMP_SENSORS 1 @@ -80,6 +80,9 @@ * If your temperature sensor has no associated heater, enter '255' as the * * heater index. * * * +* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * +* 255 * +* * \***************************************************************************/ struct { @@ -90,14 +93,14 @@ struct { } temp_sensors[NUM_TEMP_SENSORS] = { { - TT_MAX6675, + TT_INTERCOM, 0, 0 } }; #endif -#define NUM_HEATERS 1 +#define NUM_HEATERS 0 #ifdef HEATER_C /***************************************************************************\ * * @@ -119,7 +122,7 @@ struct { { { &PORTD, - PIND0, + PIND6, &OCR0A } }; @@ -238,6 +241,12 @@ struct { #define STEPPER_ENABLE_PIN DIO9 +#ifdef GEN3 + #define TX_ENABLE_PIN AIO2 + #define RX_ENABLE_PIN DIO4 + #define DEBUG_LED DIO13 +#endif + /** * list of PWM-able pins and corresponding timers * timer1 is used for step timing so don't use OC1A/OC1B @@ -273,14 +282,7 @@ struct { * */ - -// comment out the ones you don't have -#define HEATER_PIN DIO6 -#define HEATER_PWM OCR0A - -#define FAN_PIN DIO5 -#define FAN_PWM OCR0B - +// this is the scaling of internally stored PID values. 1024L is a good value #define PID_SCALE 1024L // -------------------------------------------------------------------------- diff --git a/extruder/Makefile b/extruder/Makefile new file mode 100644 index 0000000..56ddf6a --- /dev/null +++ b/extruder/Makefile @@ -0,0 +1,142 @@ +############################################################################## +# # +# FiveD on Arduino - alternative firmware for repraps # +# # +# by Triffid Hunter, Traumflug, jakepoz # +# # +# # +# This firmware is Copyright (C) 2009-2010 Michael Moon aka Triffid_Hunter # +# # +# This program 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 2 of the License, or # +# (at your option) any later version. # +# # +# This program 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 this program; if not, write to the Free Software # +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # +# # +############################################################################## + +############################################################################## +# # +# Change these to suit your application # +# # +############################################################################## + +PROGRAM = extruder + +SOURCES = $(PROGRAM).c intercom.c delay.c analog.c watchdog.c + +############################################################################## +# # +# Change these to suit your hardware # +# # +############################################################################## + +MCU_TARGET = atmega168 +F_CPU = 16000000L + +############################################################################## +# # +# These defaults should be ok, change if you need to # +# # +############################################################################## + +ARCH = avr- +CC = $(ARCH)gcc +OBJDUMP = $(ARCH)objdump +OBJCOPY = $(ARCH)objcopy + +############################################################################## +# # +# Available Defines: # +# # +# DEBUG # +# enables tons of debugging output. may cause host-side talkers to choke # +# XONXOFF # +# enables XON/XOFF flow control for stupid or crude talkers # +# ACCELERATION_REPRAP # +# enables reprap-style acceleration # +# ACCELERATION_RAMPING # +# enables start/stop ramping # +# # +############################################################################## + +DEFS = -DF_CPU=$(F_CPU) -DEXTRUDER -DGEN3 +# DEFS += "-DDEBUG=1" + +OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once +# OPTIMIZE = -O0 +CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps +LDFLAGS = -Wl,--as-needed -Wl,--gc-sections + +AVRDUDE = avrdude +AVRDUDECONF = /etc/avrdude.conf + +############################################################################## +# # +# udev rule for /dev/arduino (insert into /etc/udev/rules.d/99-local.rules) # +# SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", # +# NAME="%k", SYMLINK+="arduino", SYMLINK+="arduino_$attr{serial}", # +# MODE="0660" # +# # +############################################################################## +PROGPORT = /dev/arduino +PROGBAUD = 57600 + +OBJ = $(patsubst %.c,%.o,${SOURCES}) + +.PHONY: all program clean size +.PRECIOUS: %.o %.elf + +all: config.h $(PROGRAM).hex $(PROGRAM).lst $(PROGRAM).sym size + +program: $(PROGRAM).hex config.h + stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) + @sleep 0.1 + @stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT) + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U flash:w:$^ + stty 115200 raw ignbrk -hup -echo ixoff < $(PROGPORT) + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ + +size: $(PROGRAM).elf + @echo " SIZE Atmega168 Atmega328p Atmega644" + @$(OBJDUMP) -h $^ | perl -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (14 * 1024), 14, $$a * 100 / (30 * 1024), 30, $$a * 100 / (63 * 1024), 63 }' + @$(OBJDUMP) -h $^ | perl -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (4 * 1024), 4 }' + @$(OBJDUMP) -h $^ | perl -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (2 * 1024), 2 }' + +config.h: config.h.dist + @echo "Please review config.h, as config.h.dist is more recent." + @false + +%.o: %.c config.h + @echo " CC $@" + @$(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $(subst .o,.c,$@) + +%.elf: $(OBJ) + @echo " LINK $@" + @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +%.lst: %.elf + @echo " OBJDUMP $@" + @$(OBJDUMP) -h -S $< > $@ + +%.hex: %.elf + @echo " OBJCOPY $@" + @$(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.bin: %.elf + @echo " OBJCOPY $@" + @$(OBJCOPY) -j .text -j .data -O binary $< $@ + +%.sym: %.elf + @echo " SYM $@" + @$(OBJDUMP) -t $< | perl -ne 'BEGIN { printf " ADDR NAME SIZE\n"; } /([0-9a-f]+)\s+(\w+)\s+O\s+\.(bss|data)\s+([0-9a-f]+)\s+(\w+)/ && printf "0x%04x %-20s +%d\n", eval("0x$$1") & 0xFFFF, $$5, eval("0x$$4")' | sort -k1 > $@ diff --git a/extruder/README b/extruder/README new file mode 100644 index 0000000..3d313a2 --- /dev/null +++ b/extruder/README @@ -0,0 +1,2 @@ +Reprap Gen3 extruder controller support for Triffid_Hunter's FiveD_on_Arduino firmware +by jakepoz diff --git a/extruder/analog.c b/extruder/analog.c new file mode 120000 index 0000000..4ba410b --- /dev/null +++ b/extruder/analog.c @@ -0,0 +1 @@ +../analog.c \ No newline at end of file diff --git a/extruder/analog.h b/extruder/analog.h new file mode 120000 index 0000000..882b768 --- /dev/null +++ b/extruder/analog.h @@ -0,0 +1 @@ +../analog.h \ No newline at end of file diff --git a/extruder/arduino.h b/extruder/arduino.h new file mode 120000 index 0000000..14df5af --- /dev/null +++ b/extruder/arduino.h @@ -0,0 +1 @@ +../arduino.h \ No newline at end of file diff --git a/extruder/arduino_168_328p.h b/extruder/arduino_168_328p.h new file mode 120000 index 0000000..3940ca5 --- /dev/null +++ b/extruder/arduino_168_328p.h @@ -0,0 +1 @@ +../arduino_168_328p.h \ No newline at end of file diff --git a/extruder/config.h.dist b/extruder/config.h.dist new file mode 100644 index 0000000..b11dfb8 --- /dev/null +++ b/extruder/config.h.dist @@ -0,0 +1,79 @@ +#ifndef _CONFIG_H +#define _CONFIG_H + +#include "arduino.h" + +//RS485 Interface pins +#define RX_ENABLE_PIN DIO4 +#define TX_ENABLE_PIN AIO2 + +// Control pins for the A3949 chips +#define H1D DIO7 +#define H1E DIO5 +#define H2D DIO8 +#define H2E DIO6 + +// PWM versions of the enable_pins +#define H1E_PWM OCR0B +#define H2E_PWM OCR0A + +//Step/Dir Pins from motherboard to extruder +//IMPORTANT: Assumes that the step pin is on PCIE0 +#define E_STEP_PIN DIO10 +#define E_DIR_PIN DIO9 + +//Trimpot is on AIO0, pin 23 +#define TRIM_POT AIO0 +#define TRIM_POT_CHANNEL 0 + +//Debug LED will blink on RS485 transmission +#define DEBUG_LED DIO13 + +//Read analog voltage from thermistor +#define TEMP_PIN AIO3 +#define TEMP_PIN_CHANNEL 3 + +#define REFERENCE REFERENCE_AVCC + +// list of PWM-able pins and corresponding timers +// timer1 is used for step timing so don't use OC1A/OC1B (DIO9/DIO10) +// OC0A DIO6 +// OC0B DIO5 +// OC1A DIO9 +// OC1B DIO10 +// OC2A DIO11 +// OC2B DIO3 + +#define HEATER_PIN DIO11 +#define HEATER_PWM OCR2A + +#define BED_PIN DIO12 + +#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL)) + +/* + Intercom +*/ +#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0) +#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0) + +/* + Motors +*/ + +#define enable_motors() do { TCCR0A |= MASK(COM0A1) | MASK(COM0B1); } while (0) +#define disable_motors() do { TCCR0A &= ~MASK(COM0A1) & ~MASK(COM0B1); } while (0) + +/* + Heater +*/ + +#ifdef HEATER_PWM + #define enable_heater() do { TCCR2A |= MASK(COM2A1); } while (0) + #define disable_heater() do { TCCR2A &= ~MASK(COM2A1); } while (0) +#else + #define enable_heater() WRITE(HEATER_PIN, 1) + #define disable_heater() WRITE(HEATER_PIN, 0) +#endif + +#endif /* _CONFIG_H */ diff --git a/extruder/delay.c b/extruder/delay.c new file mode 120000 index 0000000..1df3093 --- /dev/null +++ b/extruder/delay.c @@ -0,0 +1 @@ +../delay.c \ No newline at end of file diff --git a/extruder/delay.h b/extruder/delay.h new file mode 120000 index 0000000..8c2af90 --- /dev/null +++ b/extruder/delay.h @@ -0,0 +1 @@ +../delay.h \ No newline at end of file diff --git a/extruder/extruder.c b/extruder/extruder.c new file mode 100644 index 0000000..7d11b70 --- /dev/null +++ b/extruder/extruder.c @@ -0,0 +1,229 @@ +#include +#include + +#include + +#include "intercom.h" +#include "analog.h" +#include "config.h" +#include "watchdog.h" + +static uint8_t motor_pwm; + +#define NUMTEMPS 20 +short temptable[NUMTEMPS][2] = { + {1, 841}, + {54, 255}, + {107, 209}, + {160, 184}, + {213, 166}, + {266, 153}, + {319, 142}, + {372, 132}, + {425, 124}, + {478, 116}, + {531, 108}, + {584, 101}, + {637, 93}, + {690, 86}, + {743, 78}, + {796, 70}, + {849, 61}, + {902, 50}, + {955, 34}, + {1008, 3} +}; + +void io_init(void) { + // setup I/O pins + WRITE(DEBUG_LED, 0); SET_OUTPUT(DEBUG_LED); + WRITE(H1D,0); SET_OUTPUT(H1D); + WRITE(H1E,0); SET_OUTPUT(H1E); + WRITE(H2D,0); SET_OUTPUT(H2D); + WRITE(H2E,0); SET_OUTPUT(H2E); + + SET_INPUT(TRIM_POT); + SET_INPUT(TEMP_PIN); + SET_INPUT(E_STEP_PIN); + SET_INPUT(E_DIR_PIN); + + //Enable the RS485 transceiver + SET_OUTPUT(RX_ENABLE_PIN); + SET_OUTPUT(TX_ENABLE_PIN); + disable_transmit(); + + #ifdef HEATER_PIN + WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN); + #endif + + #ifdef BED_PIN + WRITE(BED_PIN, 0); SET_OUTPUT(BED_PIN); + #endif + + #if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM) + // setup PWM timer: fast PWM, no prescaler + TCCR2A = MASK(WGM21) | MASK(WGM20); + TCCR2B = MASK(CS22); + TIMSK2 = 0; + OCR2A = 0; + OCR2B = 0; + #endif + + #if defined(H1E_PWM) && defined(H2E_PWM) + TCCR0A = MASK(WGM01) | MASK(WGM00); + TCCR0B = MASK(CS20); + TIMSK0 = 0; + OCR0A = 0; + OCR0B = 0; + #endif +} + +void motor_init(void) { + //Enable an interrupt to be triggered when the step pin changes + //This will be PCIE0 + PCICR = MASK(PCIE0); + PCMSK0 = MASK(PCINT2); +} + +ISR(PCINT0_vect) { + static uint8_t coil_pos, pwm, flag; + + if (flag == 1) flag = 0; + else flag = 1; + + //if the step pin is high, we advance the motor + if (flag) { + + //Turn on motors only on first tick to save power I guess + enable_motors(); + + //Advance the coil position + if (READ(E_DIR_PIN)) + coil_pos++; + else + coil_pos--; + + coil_pos &= 31; + + //Grab the latest motor power to use + pwm = motor_pwm; + + switch(coil_pos >> 2) { + case 0: + WRITE(H1D, 0); + WRITE(H2D, 0); + H1E_PWM = 0; + H2E_PWM = pwm; + break; + case 1: + WRITE(H1D, 1); + WRITE(H2D, 0); + H1E_PWM = pwm; + H2E_PWM = pwm; + break; + case 2: + WRITE(H1D, 1); + WRITE(H2D, 0); + H1E_PWM = pwm; + H2E_PWM = 0; + break; + case 3: + WRITE(H1D, 1); + WRITE(H2D, 1); + H1E_PWM = pwm; + H2E_PWM = pwm; + break; + case 4: + WRITE(H1D, 1); + WRITE(H2D, 1); + H1E_PWM = 0; + H2E_PWM = pwm; + break; + case 5: + WRITE(H1D, 0); + WRITE(H2D, 1); + H1E_PWM = pwm; + H2E_PWM = pwm; + break; + case 6: + WRITE(H1D, 0); + WRITE(H2D, 1); + H1E_PWM = pwm; + H2E_PWM = 0; + break; + case 7: + WRITE(H1D, 0); + WRITE(H2D, 0); + H1E_PWM = pwm; + H2E_PWM = pwm; + break; + } + } +} + +void init(void) { + // set up watchdog + wd_init(); + + // setup analog reading + analog_init(); + + // set up serial + intercom_init(); + + // set up inputs and outputs + io_init(); + + // set up extruder motor driver + motor_init(); + + // enable interrupts + sei(); + + // reset watchdog + wd_reset(); +} + + +int main (void) +{ + static uint8_t i; + static uint16_t raw_temp; + + init(); + + enable_heater(); + + start_send(); + + // main loop + for (;;) + { + wd_reset(); + + //Read motor PWM + motor_pwm = analog_read(TRIM_POT_CHANNEL) >> 2; + + //Read current temperature + raw_temp = analog_read(TEMP_PIN_CHANNEL); + + //Calculate real temperature based on lookup table + for (i = 1; i < NUMTEMPS; i++) { + if (temptable[i][0] > raw_temp) { + raw_temp = temptable[i][1] + + (temptable[i][0] - raw_temp) * (temptable[i-1][1] - temptable[i][1]) / (temptable[i][0] - temptable[i-1][0]); + + break; + } + } + + //Clamp for overflows + if (i == NUMTEMPS) raw_temp = temptable[NUMTEMPS-1][1]; + if (raw_temp > 255) raw_temp = 255; + + //Update the intercom values + update_send_cmd(raw_temp); + + HEATER_PWM = get_read_cmd(); + } +} diff --git a/extruder/intercom.c b/extruder/intercom.c new file mode 100644 index 0000000..35cd1f3 --- /dev/null +++ b/extruder/intercom.c @@ -0,0 +1,220 @@ +#ifdef GEN3 + +#include "intercom.h" + +#include + +#include "config.h" +#include "delay.h" + +#define INTERCOM_BAUD 57600 + +#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0) +#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0) + +/* + Defines a super simple intercom interface using the RS485 modules + + Host will say: START1 START2 PWM_CMD PWM_CHK + Extruder will reply: START1 START2 TMP_CMD TMP_CHK + + CHK = 255-CMD, if they match do the work, if not, ignore this packet + + in a loop +*/ + + +#define START1 0xAA +#define START2 0x55 + +typedef enum { + SEND_START1, + SEND_START2, + SEND_CMD, + SEND_CHK, + SEND_DONE, + + READ_START1, + READ_START2, + READ_CMD, + READ_CHK, +} intercom_state_e; + + +intercom_state_e state = READ_START1; +uint8_t cmd, chk, send_cmd, read_cmd; + +void intercom_init(void) +{ +#ifdef HOST + #if INTERCOM_BAUD > 38401 + UCSR1A = MASK(U2X1); + UBRR1 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5); + #else + UCSR1A = 0; + UBRR1 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5); + #endif + UCSR1B = MASK(RXEN1) | MASK(TXEN1); + UCSR1C = MASK(UCSZ11) | MASK(UCSZ10); + + UCSR1B |= MASK(RXCIE1) | MASK(TXCIE1); +#else + #if INTERCOM_BAUD > 38401 + UCSR0A = MASK(U2X0); + UBRR0 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5); + #else + UCSR0A = 0; + UBRR0 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5); + #endif + UCSR0B = MASK(RXEN0) | MASK(TXEN0); + UCSR0C = MASK(UCSZ01) | MASK(UCSZ00); + + UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0); +#endif +} + +void update_send_cmd(uint8_t new_send_cmd) { + send_cmd = new_send_cmd; +} + +uint8_t get_read_cmd(void) { + return read_cmd; +} + +static void write_byte(uint8_t val) { +#ifdef HOST + UDR1 = val; +#else + UDR0 = val; +#endif +} + + +void start_send(void) { + state = SEND_START1; + enable_transmit(); + delay_us(15); + //Enable interrupts so we can send next characters +#ifdef HOST + UCSR1B |= MASK(UDRIE1); +#else + UCSR0B |= MASK(UDRIE0); +#endif +} + +static void finish_send(void) { + state = READ_START1; + disable_transmit(); +} + + +/* + Interrupts, UART 0 for mendel +*/ +#ifdef HOST +ISR(USART1_RX_vect) +#else +ISR(USART_RX_vect) +#endif +{ + static uint8_t c; + +#ifdef HOST + c = UDR1; + UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); +#else + c = UDR0; + UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); +#endif + + if (state >= READ_START1) { + + switch(state) { + case READ_START1: + if (c == START1) state = READ_START2; + break; + case READ_START2: + if (c == START2) state = READ_CMD; + else state = READ_START1; + break; + case READ_CMD: + cmd = c; + state = READ_CHK; + break; + case READ_CHK: + chk = c; + + if (chk == 255 - cmd) { + //Values are correct, do something useful + WRITE(DEBUG_LED,1); + read_cmd = cmd; +#ifdef EXTRUDER + start_send(); +#endif + } + else + { + state = READ_START1; + } + break; + default: + break; + } + } + +} + +#ifdef HOST +ISR(USART1_TX_vect) +#else +ISR(USART_TX_vect) +#endif +{ + if (state == SEND_DONE) { + finish_send(); + + +#ifdef HOST + UCSR1B &= ~MASK(TXCIE1); +#else + UCSR0B &= ~MASK(TXCIE0); +#endif + } +} + +#ifdef HOST +ISR(USART1_UDRE_vect) +#else +ISR(USART_UDRE_vect) +#endif +{ + switch(state) { + case SEND_START1: + write_byte(START1); + state = SEND_START2; + break; + case SEND_START2: + write_byte(START2); + state = SEND_CMD; + break; + case SEND_CMD: + write_byte(send_cmd); + state = SEND_CHK; + break; + case SEND_CHK: + write_byte(255 - send_cmd); + state = SEND_DONE; +#ifdef HOST + UCSR1B &= ~MASK(UDRIE1); + UCSR1B |= MASK(TXCIE1); +#else + UCSR0B &= ~MASK(UDRIE0); + UCSR0B |= MASK(TXCIE0); +#endif + break; + default: + break; + } +} + +#endif /* GEN3 */ diff --git a/extruder/intercom.h b/extruder/intercom.h new file mode 100644 index 0000000..5a6ab8e --- /dev/null +++ b/extruder/intercom.h @@ -0,0 +1,17 @@ +#ifndef _INTERCOM_H +#define _INTERCOM_H + +#include + +// initialise serial subsystem +void intercom_init(void); + +//Update the message we are sending over intercom +void update_send_cmd(uint8_t new_send_cmd); + +void start_send(void); + +//Read the message we are receiving over intercom +uint8_t get_read_cmd(void); + +#endif /* _INTERCOM_H */ diff --git a/extruder/watchdog.c b/extruder/watchdog.c new file mode 120000 index 0000000..f5d6bfa --- /dev/null +++ b/extruder/watchdog.c @@ -0,0 +1 @@ +../watchdog.c \ No newline at end of file diff --git a/extruder/watchdog.h b/extruder/watchdog.h new file mode 120000 index 0000000..20df3e8 --- /dev/null +++ b/extruder/watchdog.h @@ -0,0 +1 @@ +../watchdog.h \ No newline at end of file diff --git a/gcode_parse.c b/gcode_parse.c index 53e0de1..343656c 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -192,11 +192,9 @@ void gcode_parse_char(uint8_t c) { // but it takes less code, less memory and loses no precision if we do it here instead if ((next_target.M == 104) || (next_target.M == 109)) next_target.S = decfloat_to_int(&read_digit, 4, 1); - #ifdef HEATER_PIN // if this is heater PID stuff, multiply by PID_SCALE because we divide by PID_SCALE later on else if ((next_target.M >= 130) && (next_target.M <= 132)) next_target.S = decfloat_to_int(&read_digit, PID_SCALE, 1); - #endif else next_target.S = decfloat_to_int(&read_digit, 1, 1); if (debug_flags & DEBUG_ECHO) diff --git a/gcode_process.c b/gcode_process.c index 542d064..4e1a9d9 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -199,7 +199,6 @@ void process_gcode_command() { case 104: temp_set(next_target.P, next_target.S); if (next_target.S) { - enable_heater(); power_on(); } else { @@ -213,15 +212,15 @@ void process_gcode_command() { break; // M106- fan on - #ifdef FAN_PIN + #if NUM_HEATERS > 1 case 106: - enable_fan(); + heater_set(1, 255); break; // M107- fan off case 107: - disable_fan(); + heater_set(1, 0); break; - #endif + #endif // M109- set temp and wait case 109: @@ -262,7 +261,7 @@ void process_gcode_command() { serial_writestr_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 HEATER_COUNT:1\n")); break; - #ifdef HEATER_PIN + #if NUM_HEATERS > 0 // M130- heater P factor case 130: if (next_target.seen_S) @@ -291,7 +290,7 @@ void process_gcode_command() { case 134: heater_save_settings(); break; - #endif /* HEATER_PIN */ + #endif /* NUM_HEATERS > 0 */ // M190- power on case 190: diff --git a/heater.c b/heater.c index 259662c..68c6798 100644 --- a/heater.c +++ b/heater.c @@ -47,8 +47,18 @@ typedef struct { EE_factor EEMEM EE_factors[NUM_HEATERS]; void heater_init() { - // read factors from eeprom + #if NUM_HEATERS > 0 uint8_t i; + // setup pins + for (i = 0; i < NUM_HEATERS; i++) { + *(heaters[i].heater_port) &= ~heaters[i].heater_pin; + // DDR is always 1 address below PORT. ugly code but saves ram and an extra field in heaters[] which will never be used anywhere but here + *((volatile uint8_t *) (heaters[i].heater_port - 1)) |= heaters[i].heater_pin; + if (heaters[i].heater_pwm) + *heaters[i].heater_pwm = 0; + } + + // read factors from eeprom for (i = 0; i < NUM_HEATERS; i++) { heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor); heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor); @@ -62,6 +72,7 @@ void heater_init() { heaters_pid[i].i_limit = DEFAULT_I_LIMIT; } } + #endif } void heater_save_settings() { @@ -121,6 +132,7 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { } void heater_set(uint8_t index, uint8_t value) { + #if NUM_HEATERS > 0 if (heaters[index].heater_pwm) { *heaters[index].heater_pwm = value; } @@ -130,6 +142,7 @@ void heater_set(uint8_t index, uint8_t value) { else *heaters[index].heater_port &= ~MASK(heaters[index].heater_pin); } + #endif } void pid_set_p(uint8_t index, int32_t p) { diff --git a/intercom.c b/intercom.c new file mode 120000 index 0000000..a627b1f --- /dev/null +++ b/intercom.c @@ -0,0 +1 @@ +extruder/intercom.c \ No newline at end of file diff --git a/intercom.h b/intercom.h new file mode 120000 index 0000000..c515963 --- /dev/null +++ b/intercom.h @@ -0,0 +1 @@ +extruder/intercom.h \ No newline at end of file diff --git a/mendel.c b/mendel.c index 08fb037..aae3f35 100644 --- a/mendel.c +++ b/mendel.c @@ -46,28 +46,18 @@ void io_init(void) { WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN); WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN); - #ifdef HEATER_PIN - WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN); - #endif + // setup PWM timer: fast PWM, no prescaler + TCCR0A = MASK(WGM01) | MASK(WGM00); + TCCR0B = MASK(CS00); + TIMSK0 = 0; + OCR0A = 0; + OCR0B = 255; - #ifdef FAN_PIN - WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN); - #endif - - #if defined(HEATER_PWM) || defined(FAN_PWM) - // setup PWM timer: fast PWM, no prescaler - TCCR0A = MASK(WGM01) | MASK(WGM00); - TCCR0B = MASK(CS00); - TIMSK0 = 0; - OCR0A = 0; - OCR0B = 255; - - TCCR2A = MASK(WGM21) | MASK(WGM20); - TCCR2B = MASK(CS20); - TIMSK2 = 0; - OCR2A = 0; - OCR2B = 0; - #endif + TCCR2A = MASK(WGM21) | MASK(WGM20); + TCCR2B = MASK(CS20); + TIMSK2 = 0; + OCR2A = 0; + OCR2B = 0; #ifdef STEPPER_ENABLE_PIN power_off(); @@ -102,7 +92,10 @@ void init(void) { // start up analog read interrupt loop, if anything uses analog as determined by ANALOG_MASK in your config.h analog_init(); - + + // set up temperature inputs + temp_init(); + // enable interrupts sei(); @@ -114,12 +107,14 @@ void init(void) { } -void clock_250ms(void) { +void clock_10ms(void) { // reset watchdog wd_reset(); - + temp_tick(); +} +void clock_250ms(void) { if (steptimeout > (30 * 4)) { power_off(); } @@ -156,6 +151,10 @@ int main (void) gcode_parse_char(c); } + ifclock(CLOCK_FLAG_10MS) { + clock_10ms(); + } + ifclock(CLOCK_FLAG_250MS) { clock_250ms(); } diff --git a/temp.c b/temp.c index a662304..e587a39 100644 --- a/temp.c +++ b/temp.c @@ -9,11 +9,17 @@ #include "debug.h" #include "sersendf.h" #include "heater.h" +#ifdef GEN3 + #include "intercom.h" +#endif typedef enum { TT_THERMISTOR, TT_MAX6675, TT_AD595 +#ifdef GEN3 + , TT_INTERCOM +#endif } temp_types; typedef enum { @@ -71,6 +77,38 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = { #include "analog.h" #endif +void temp_init() { + uint8_t i; + for (i = 0; i < NUM_TEMP_SENSORS; i++) { + switch(temp_sensors[i].temp_type) { + #ifdef TEMP_MAX6675 + // initialised when read +/* case TT_MAX6675: + break;*/ + #endif + + #ifdef TEMP_THERMISTOR + // handled by analog_init() +/* case TT_THERMISTOR: + break;*/ + #endif + + #ifdef TEMP_AD595 + // handled by analog_init() +/* case TT_AD595: + break;*/ + #endif + + #ifdef GEN3 + case TT_INTERCOM: + intercom_init(); + update_send_cmd(0); + break; + #endif + } + } +} + void temp_sensor_tick() { uint8_t i = 0, all_within_range = 1; for (; i < NUM_TEMP_SENSORS; i++) { @@ -87,9 +125,9 @@ void temp_sensor_tick() { #ifdef TEMP_MAX6675 case TT_MAX6675: #ifdef PRR - PRR &= ~MASK(PRSPI); + PRR &= ~MASK(PRSPI); #elif defined PRR0 - PRR0 &= ~MASK(PRSPI); + PRR0 &= ~MASK(PRSPI); #endif SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0); @@ -127,7 +165,7 @@ void temp_sensor_tick() { } } - // FIXME: placeholder number + // this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms temp_sensors_runtime[i].next_read_time = 25; break; @@ -152,7 +190,6 @@ void temp_sensor_tick() { if (j == NUMTEMPS) temp = temptable[NUMTEMPS-1][1]; - // FIXME: placeholder number temp_sensors_runtime[i].next_read_time = 0; break; @@ -166,11 +203,21 @@ void temp_sensor_tick() { // >>8 instead of >>10 because internal temp is stored as 14.2 fixed point temp = (temp * 500L) >> 8; - // FIXME: placeholder number - temp_sensors[i].next_read_time = 0; + temp_sensors_runtime[i].next_read_time = 0; break; #endif /* TEMP_AD595 */ + + #ifdef GEN3 + case TT_INTERCOM: + temp = get_read_cmd() << 2; + + start_send(); + + temp_sensors_runtime[i].next_read_time = 0; + + break; + #endif /* GEN3 */ } temp_sensors_runtime[i].last_read_temp = temp; @@ -202,6 +249,10 @@ uint8_t temp_achieved() { void temp_set(uint8_t index, uint16_t temperature) { temp_sensors_runtime[index].target_temp = temperature; temp_sensors_runtime[index].temp_residency = 0; +#ifdef GEN3 + if (temp_sensors[index].temp_type == TT_INTERCOM) + update_send_cmd(temperature >> 2); +#endif } void temp_print(uint8_t index) { diff --git a/temp.h b/temp.h index 5555b8e..c912760 100644 --- a/temp.h +++ b/temp.h @@ -13,6 +13,8 @@ we still need to specify which analog pins we use in machine.h for the analog se #define temp_tick temp_sensor_tick +void temp_init(void); + void temp_sensor_tick(void); uint8_t temp_achieved(void); diff --git a/timer.c b/timer.c index 2f4586f..ddd5e60 100644 --- a/timer.c +++ b/timer.c @@ -6,6 +6,7 @@ volatile uint32_t next_step_time; +uint8_t clock_counter_10ms = 0; uint8_t clock_counter_250ms = 0; uint8_t clock_counter_1s = 0; volatile uint8_t clock_flag = 0; @@ -30,14 +31,21 @@ ISR(TIMER1_CAPT_vect) { /* clock stuff */ - clock_counter_250ms += (TICK_TIME / (F_CPU / 1000)); - if (clock_counter_250ms >= 250) { - clock_counter_250ms -= 250; - clock_flag |= CLOCK_FLAG_250MS; - clock_counter_1s += 1; - if (clock_counter_1s >= 4) { - clock_counter_1s -= 4; - clock_flag |= CLOCK_FLAG_1S; + clock_counter_10ms += (TICK_TIME / (F_CPU / 1000)); + if (clock_counter_10ms >= 10) { + clock_counter_10ms -= 10; + clock_flag |= CLOCK_FLAG_10MS; + + clock_counter_250ms += 10; + if (clock_counter_250ms >= 250) { + clock_counter_250ms -= 250; + clock_flag |= CLOCK_FLAG_250MS; + + clock_counter_1s += 1; + if (clock_counter_1s >= 4) { + clock_counter_1s -= 4; + clock_flag |= CLOCK_FLAG_1S; + } } } } diff --git a/timer.h b/timer.h index 2626860..dd6b6be 100644 --- a/timer.h +++ b/timer.h @@ -13,8 +13,9 @@ clock stuff */ extern volatile uint8_t clock_flag; -#define CLOCK_FLAG_250MS 1 -#define CLOCK_FLAG_1S 2 +#define CLOCK_FLAG_10MS 1 +#define CLOCK_FLAG_250MS 2 +#define CLOCK_FLAG_1S 4 #define ifclock(F) for (;clock_flag & (F);clock_flag &= ~(F)) /* From 64f027f54ea8d94c9e3c98a5b744896953abf1b0 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 26 Oct 2010 01:02:07 +1100 Subject: [PATCH 14/82] ensure analog pins are inputs --- analog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/analog.c b/analog.c index 9ae7b59..2a1b4e5 100644 --- a/analog.c +++ b/analog.c @@ -18,14 +18,17 @@ void analog_init() { #elif defined PRR0 PRR0 &= ~MASK(PRADC); #endif + ADMUX = REFERENCE; + // ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz. ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0); adc_counter = 0; adc_running_mask = 1; - DIDR0 = ANALOG_MASK & 0x1F; + DDRC &= ANALOG_MASK; + DIDR0 = ANALOG_MASK & 0x3F; // now we start the first conversion and leave the rest to the interrupt ADCSRA |= MASK(ADIE) | MASK(ADSC); From 7aa99095ff81f83a5d68a02317c8408d336f96db Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 26 Oct 2010 01:03:06 +1100 Subject: [PATCH 15/82] exclude code for no-ooze if disabled --- config.h.dist | 2 +- gcode_process.c | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/config.h.dist b/config.h.dist index b9cdcf8..853bc00 100644 --- a/config.h.dist +++ b/config.h.dist @@ -38,7 +38,7 @@ #define TEMP_HYSTERESIS 20 #define TEMP_RESIDENCY_TIME 60 -// this is how many steps to suck back the filament by when we stop +// this is how many steps to suck back the filament by when we stop. set to zero to disable #define E_STARTSTOP_STEPS 20 /* diff --git a/gcode_process.c b/gcode_process.c index 4e1a9d9..f91ace8 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -173,26 +173,30 @@ void process_gcode_command() { if (temp_achieved() == 0) { enqueue(NULL); } - do { - // backup feedrate, move E very quickly then restore feedrate - backup_f = startpoint.F; - startpoint.F = MAXIMUM_FEEDRATE_E; - SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); - startpoint.F = backup_f; - } while (0); + #if E_STARTSTOP_STEPS > 0 + do { + // backup feedrate, move E very quickly then restore feedrate + backup_f = startpoint.F; + startpoint.F = MAXIMUM_FEEDRATE_E; + SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); + startpoint.F = backup_f; + } while (0); + #endif break; // M102- extruder reverse // M103- extruder off case 103: - do { - // backup feedrate, move E very quickly then restore feedrate - backup_f = startpoint.F; - startpoint.F = MAXIMUM_FEEDRATE_E; - SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); - startpoint.F = backup_f; - } while (0); + #if E_STARTSTOP_STEPS > 0 + do { + // backup feedrate, move E very quickly then restore feedrate + backup_f = startpoint.F; + startpoint.F = MAXIMUM_FEEDRATE_E; + SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E); + startpoint.F = backup_f; + } while (0); + #endif break; // M104- set temperature From 25b8f9ebfbf3b9999db3b4d75e84bc73e2ff3ac0 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 26 Oct 2010 01:07:07 +1100 Subject: [PATCH 16/82] update "size" target in extruder/Makefile --- extruder/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extruder/Makefile b/extruder/Makefile index 56ddf6a..dd18c29 100644 --- a/extruder/Makefile +++ b/extruder/Makefile @@ -65,6 +65,8 @@ OBJCOPY = $(ARCH)objcopy # enables reprap-style acceleration # # ACCELERATION_RAMPING # # enables start/stop ramping # +# GEN3 # +# build for standard reprap electronics instead of your custom rig # # # ############################################################################## @@ -109,9 +111,9 @@ clean: size: $(PROGRAM).elf @echo " SIZE Atmega168 Atmega328p Atmega644" - @$(OBJDUMP) -h $^ | perl -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (14 * 1024), 14, $$a * 100 / (30 * 1024), 30, $$a * 100 / (63 * 1024), 63 }' - @$(OBJDUMP) -h $^ | perl -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (4 * 1024), 4 }' - @$(OBJDUMP) -h $^ | perl -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, $$a * 100 / (1 * 1024), 1, $$a * 100 / (2 * 1024), 2, $$a * 100 / (2 * 1024), 2 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (14 * 1024)), 14, ceil($$a * 100 / (30 * 1024)), 30, ceil($$a * 100 / (63 * 1024)), 63 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (4 * 1024)), 4 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (2 * 1024)), 2 }' config.h: config.h.dist @echo "Please review config.h, as config.h.dist is more recent." From 38cf934594c3d1cb553d0e36207355a7c68ea54a Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 26 Oct 2010 11:26:01 +1100 Subject: [PATCH 17/82] further integration of gen3 logic --- Makefile | 4 +- arduino_1280.h | 3 +- arduino_168_328p.h | 2 +- arduino_644.h | 36 ++++++------ config.h.dist | 140 +++++++++++++++++---------------------------- dda.c | 5 ++ gcode_process.c | 3 +- mendel.c | 24 ++++---- pinio.c | 20 +++++++ pinio.h | 46 +++++++++++++++ 10 files changed, 162 insertions(+), 121 deletions(-) create mode 100644 pinio.c create mode 100644 pinio.h diff --git a/Makefile b/Makefile index c5a2cb8..7bea58d 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c pinio.c ############################################################################## # # @@ -117,7 +117,7 @@ clean: size: $(PROGRAM).elf @echo " SIZE Atmega168 Atmega328p Atmega644" - @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (14 * 1024)), 14, ceil($$a * 100 / (30 * 1024)), 30, ceil($$a * 100 / (63 * 1024)), 63 }' + @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (15 * 1024)), 15, ceil($$a * 100 / (31 * 1024)), 31, ceil($$a * 100 / (63 * 1024)), 63 }' @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (4 * 1024)), 4 }' @$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes (%2d%% of %2dkb) (%2d%% of %2dkb) (%2d%% of %2dkb)\n", $$a, ceil($$a * 100 / (1 * 1024)), 1, ceil($$a * 100 / (2 * 1024)), 2, ceil($$a * 100 / (2 * 1024)), 2 }' diff --git a/arduino_1280.h b/arduino_1280.h index 81594db..47dd05b 100644 --- a/arduino_1280.h +++ b/arduino_1280.h @@ -29,7 +29,8 @@ #define OC5B DIO45 #define OC5C DIO44 -// #define ICP1 NULL /* not brought out on the Arduino Mega, remove line as not used ?? */ +// change for your board +#define DEBUG_LED DIO21 /* pins diff --git a/arduino_168_328p.h b/arduino_168_328p.h index 77b3242..5431c3e 100644 --- a/arduino_168_328p.h +++ b/arduino_168_328p.h @@ -20,7 +20,7 @@ #define OC2A DIO11 #define OC2B DIO3 -#define ICP1 DIO8 +#define DEBUG_LED AIO5 /* pins diff --git a/arduino_644.h b/arduino_644.h index 9debeda..11d5aa7 100644 --- a/arduino_644.h +++ b/arduino_644.h @@ -1,27 +1,31 @@ // UART -#define RXD DIO0 -#define TXD DIO1 +#define RXD DIO8 +#define TXD DIO9 +#define RXD0 DIO8 +#define TXD0 DIO9 + +#define RXD1 DIO10 +#define TXD1 DIO11 // SPI -#define SCK DIO13 -#define MISO DIO12 -#define MOSI DIO11 -#define SS DIO10 +#define SCK DIO7 +#define MISO DIO6 +#define MOSI DIO5 +#define SS DIO4 // TWI (I2C) -#define SCL AIO5 -#define SDA AIO4 +#define SCL DIO16 +#define SDA DIO17 // timers and PWM -#define OC0A DIO6 -#define OC0B DIO5 -#define OC1A DIO9 -#define OC1B DIO10 -#define OC2A DIO11 -#define OC2B DIO3 - -#define ICP1 DIO8 +#define OC0A DIO3 +#define OC0B DIO4 +#define OC1A DIO13 +#define OC1B DIO12 +#define OC2A DIO15 +#define OC2B DIO14 +#define DEBUG_LED DIO0 /* pins */ diff --git a/config.h.dist b/config.h.dist index 853bc00..c9b0538 100644 --- a/config.h.dist +++ b/config.h.dist @@ -118,14 +118,14 @@ struct { volatile uint8_t *heater_port; uint8_t heater_pin; volatile uint8_t *heater_pwm; -} heaters[NUM_HEATERS] = +} heaters[NUM_HEATERS]/* = { { &PORTD, PIND6, &OCR0A } -}; +}*/; #endif // temperature history count. higher values make PID derivative term more stable at the expense of reaction time @@ -194,57 +194,57 @@ struct { #include "arduino.h" -/* - RESERVED pins - we NEED these for communication -*/ - -#define RESERVED_RXD DIO0 -#define RESERVED_TXD DIO1 - -/* - these pins are used for the MAX6675 - Arduino Mega has SPI on different pins -*/ -#if defined (__AVR_ATmega1280__) - #define RESERVED_SCK DIO52 - #define RESERVED_MISO DIO50 - #define RESERVED_MOSI DIO51 - #define RESERVED_SS DIO53 -#else - #define RESERVED_SCK DIO13 - #define RESERVED_MISO DIO12 - #define RESERVED_MOSI DIO11 - #define RESERVED_SS DIO10 -#endif - -/* - user defined pins - adjust to suit your electronics, - or adjust your electronics to suit this -*/ - -#define X_STEP_PIN AIO0 -#define X_DIR_PIN AIO1 -#define X_MIN_PIN AIO2 - -#define Y_STEP_PIN AIO3 -#define Y_DIR_PIN AIO4 -#define Y_MIN_PIN AIO5 - -#define Z_STEP_PIN DIO2 -#define Z_DIR_PIN DIO3 -#define Z_MIN_PIN DIO4 - -#define E_STEP_PIN DIO7 -#define E_DIR_PIN DIO8 - -#define STEPPER_ENABLE_PIN DIO9 - #ifdef GEN3 - #define TX_ENABLE_PIN AIO2 - #define RX_ENABLE_PIN DIO4 - #define DEBUG_LED DIO13 + // this is official reprap motherboard pinout + #define TX_ENABLE_PIN DIO12 + #define RX_ENABLE_PIN DIO13 + + #define X_STEP_PIN DIO15 + #define X_DIR_PIN DIO18 + #define X_MIN_PIN DIO20 + #define X_MAX_PIN DIO21 + #define X_ENABLE_PIN DIO19 + + #define Y_STEP_PIN DIO23 + #define Y_DIR_PIN DIO22 + #define Y_MIN_PIN AIO6 + #define Y_MAX_PIN AIO5 + #define Y_ENABLE_PIN DIO7 + + #define Z_STEP_PIN AIO4 + #define Z_DIR_PIN AIO3 + #define Z_MIN_PIN AIO1 + #define Z_MAX_PIN AIO0 + #define Z_ENABLE_PIN AIO2 + + #define E_STEP_PIN DIO16 + #define E_DIR_PIN DIO17 + + #define SD_CARD_DETECT DIO2 + #define SD_WRITE_PROTECT DIO3 +#else + /* + user defined pins + adjust to suit your electronics, + or adjust your electronics to suit this + */ + + #define X_STEP_PIN AIO0 + #define X_DIR_PIN AIO1 + #define X_MIN_PIN AIO2 + + #define Y_STEP_PIN AIO3 + #define Y_DIR_PIN AIO4 + #define Y_MIN_PIN AIO5 + + #define Z_STEP_PIN DIO2 + #define Z_DIR_PIN DIO3 + #define Z_MIN_PIN DIO4 + + #define E_STEP_PIN DIO7 + #define E_DIR_PIN DIO8 + + #define PS_ON_PIN DIO9 #endif /** @@ -285,40 +285,4 @@ struct { // this is the scaling of internally stored PID values. 1024L is a good value #define PID_SCALE 1024L -// -------------------------------------------------------------------------- -// you shouldn't need to edit anything below this line - -/* - fan -*/ - -#ifdef FAN_PIN - #ifdef FAN_PWM - #define enable_fan() do { TCCR0A |= MASK(COM0B1); } while (0) - #define disable_fan() do { TCCR0A &= ~MASK(COM0B1); } while (0) - #else - #define enable_fan() WRITE(FAN_PIN, 1) - #define disable_fan() WRITE(FAN_PIN, 0); - #endif -#else - #define enable_fan() if (0) {} - #define disable_fan() if (0) {} -#endif - -/* - Stepper Enable (ATX PSU pwr_good signal?) -*/ - -#ifdef STEPPER_ENABLE_PIN - // for connection to stepper driver ENABLE pins (negative asserted) -// #define power_on() WRITE(STEPPER_ENABLE_PIN, 0) -// #define power_off() WRITE(STEPPER_ENABLE_PIN, 1) - // for connection to ATX PSU PWR_ON signal - #define power_on() do { WRITE(STEPPER_ENABLE_PIN, 0); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0) - #define power_off() SET_INPUT(STEPPER_ENABLE_PIN) -#else - #define power_on() if (0) {} - #define power_off() if (0) {} -#endif - #endif /* _CONFIG_H */ diff --git a/dda.c b/dda.c index 44c2c1e..c35e0bf 100644 --- a/dda.c +++ b/dda.c @@ -9,6 +9,7 @@ #include "dda_queue.h" #include "debug.h" #include "sersendf.h" +#include "pinio.h" /* X Stepper @@ -232,6 +233,10 @@ void dda_create(DDA *dda, TARGET *target) { // get steppers ready to go steptimeout = 0; power_on(); + x_enable(); + y_enable(); + if (dda->z_delta) + z_enable(); dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter = -(dda->total_steps >> 1); diff --git a/gcode_process.c b/gcode_process.c index f91ace8..243bef5 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -13,6 +13,7 @@ #include "heater.h" #include "timer.h" #include "sersendf.h" +#include "pinio.h" /**************************************************************************** * * @@ -230,8 +231,8 @@ void process_gcode_command() { case 109: temp_set(next_target.P, next_target.S); if (next_target.S) { - enable_heater(); power_on(); + enable_heater(); } else { disable_heater(); diff --git a/mendel.c b/mendel.c index aae3f35..76e8305 100644 --- a/mendel.c +++ b/mendel.c @@ -16,6 +16,7 @@ #include "sersendf.h" #include "heater.h" #include "analog.h" +#include "pinio.h" void io_init(void) { // disable modules we don't use @@ -71,7 +72,6 @@ void io_init(void) { } void init(void) { - // set up watchdog wd_init(); @@ -107,13 +107,6 @@ void init(void) { } -void clock_10ms(void) { - // reset watchdog - wd_reset(); - - temp_tick(); -} - void clock_250ms(void) { if (steptimeout > (30 * 4)) { power_off(); @@ -138,6 +131,17 @@ void clock_250ms(void) { } } +void clock_10ms(void) { + // reset watchdog + wd_reset(); + + temp_tick(); + + ifclock(CLOCK_FLAG_250MS) { + clock_250ms(); + } +} + int main (void) { init(); @@ -154,9 +158,5 @@ int main (void) ifclock(CLOCK_FLAG_10MS) { clock_10ms(); } - - ifclock(CLOCK_FLAG_250MS) { - clock_250ms(); - } } } diff --git a/pinio.c b/pinio.c new file mode 100644 index 0000000..f21fe66 --- /dev/null +++ b/pinio.c @@ -0,0 +1,20 @@ +#include "pinio.h" + +void power_off() { + #ifdef X_ENABLE_PIN + x_disable(); + #endif + #ifdef Y_ENABLE_PIN + y_disable(); + #endif + #ifdef Z_ENABLE_PIN + z_disable(); + #endif + + #ifdef STEPPER_ENABLE_PIN + SET_INPUT(STEPPER_ENABLE_PIN); + #endif + #ifdef PS_ON_PIN + SET_INPUT(PS_ON_PIN); + #endif +} diff --git a/pinio.h b/pinio.h new file mode 100644 index 0000000..ab40014 --- /dev/null +++ b/pinio.h @@ -0,0 +1,46 @@ +#ifndef _PINIO_H +#define _PINIO_H + +/* +Power +*/ + +#ifdef STEPPER_ENABLE_PIN + #define power_on() do { WRITE(STEPPER_ENABLE_PIN, 0); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0) +#elif defined PS_ON_PIN + #define power_on() do { WRITE(PS_ON_PIN, 0); SET_OUTPUT(PS_ON_PIN); } while (0) +#else + #define power_on() do { } while (0) +#endif + +void power_off(void); + +/* +Stepper Enable Pins +*/ + +#ifdef X_ENABLE_PIN + #define x_enable() do { WRITE(X_ENABLE_PIN, 0); SET_OUTPUT(X_ENABLE_PIN); } while (0) + #define x_disable() do { WRITE(X_ENABLE_PIN, 1); SET_OUTPUT(X_ENABLE_PIN); } while (0) +#else + #define x_enable() do { } while (0) + #define x_disable() do { } while (0) +#endif + +#ifdef Y_ENABLE_PIN + #define y_enable() do { WRITE(Y_ENABLE_PIN, 0); SET_OUTPUT(Y_ENABLE_PIN); } while (0) + #define y_disable() do { WRITE(Y_ENABLE_PIN, 1); SET_OUTPUT(Y_ENABLE_PIN); } while (0) +#else + #define y_enable() do { } while (0) + #define y_disable() do { } while (0) +#endif + +#ifdef Z_ENABLE_PIN + #define z_enable() do { WRITE(Z_ENABLE_PIN, 0); SET_OUTPUT(Z_ENABLE_PIN); } while (0) + #define z_disable() do { WRITE(Z_ENABLE_PIN, 1); SET_OUTPUT(Z_ENABLE_PIN); } while (0) +#else + #define z_enable() do { } while (0) + #define z_disable() do { } while (0) +#endif + +#endif /* _PINIO_H */ From 1e287dd6c3c630786eb9e90c21a0ba1b43bcf7c2 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 27 Oct 2010 14:07:09 +1100 Subject: [PATCH 18/82] changes by jv4779 via pull request 14 --- analog.c | 45 ++++++++++++++++++++++++++++++++++----------- config.h.dist | 2 +- temp.c | 38 ++++++++++++++++++-------------------- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/analog.c b/analog.c index 2a1b4e5..162b429 100644 --- a/analog.c +++ b/analog.c @@ -9,6 +9,32 @@ uint8_t adc_running_mask, adc_counter; +#if ANALOG_MASK & 1 + #define ANALOG_START 0 + #define ANALOG_START_MASK 1 +#elif ANALOG_MASK & 2 + #define ANALOG_START 1 + #define ANALOG_START_MASK 2 +#elif ANALOG_MASK & 4 + #define ANALOG_START 2 + #define ANALOG_START_MASK 4 +#elif ANALOG_MASK & 8 + #define ANALOG_START 3 + #define ANALOG_START_MASK 8 +#elif ANALOG_MASK & 16 + #define ANALOG_START 4 + #define ANALOG_START_MASK 16 +#elif ANALOG_MASK & 32 + #define ANALOG_START 5 + #define ANALOG_START_MASK 32 +#elif ANALOG_MASK & 64 + #define ANALOG_START 6 + #define ANALOG_START_MASK 64 +#elif ANALOG_MASK & 128 + #define ANALOG_START 7 + #define ANALOG_START_MASK 128 +#endif + volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss"))); void analog_init() { @@ -35,7 +61,7 @@ void analog_init() { #endif } -ISR(ADC_vect) { +ISR(ADC_vect, ISR_NOBLOCK) { // emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts adc_result[ADMUX & 0x0F] = ADC; // find next channel @@ -43,11 +69,8 @@ ISR(ADC_vect) { adc_counter++; adc_running_mask <<= 1; if (adc_counter == 8) { - adc_counter = 0; - adc_running_mask = 1; - - // relax interrupt use for analog subsystem- stop after last analog read - ADCSRA &= ~MASK(ADIE); + adc_counter = ANALOG_START; + adc_running_mask = ANALOG_START_MASK; } } while ((adc_running_mask & ANALOG_MASK) == 0); @@ -57,19 +80,19 @@ ISR(ADC_vect) { } uint16_t analog_read(uint8_t channel) { - uint8_t sreg; uint16_t r; + + uint8_t sreg; // save interrupt flag sreg = SREG; // disable interrupts cli(); + // atomic 16-bit copy r = adc_result[channel]; + // restore interrupt flag SREG = sreg; - - // re-enable analog read loop so we can get new values - ADCSRA |= MASK(ADIE); - + return r; } diff --git a/config.h.dist b/config.h.dist index c9b0538..a9ebbbd 100644 --- a/config.h.dist +++ b/config.h.dist @@ -178,7 +178,7 @@ struct { REFERENCE - which analog reference to use. see analog.h for choices ANALOG_MASK - which analog inputs we will be using, bitmask. eg; #define ANALOG_MASK MASK(AIO0_PIN) | MASK(3) for AIN0 and AIN3 */ -#define REFERENCE REFERENCE_AREF +#define REFERENCE REFERENCE_AVCC #ifndef ANALOG_MASK #define ANALOG_MASK 0 diff --git a/temp.c b/temp.c index e587a39..92edd3c 100644 --- a/temp.c +++ b/temp.c @@ -117,9 +117,6 @@ void temp_sensor_tick() { } else { uint16_t temp = 0; - #ifdef TEMP_THERMISTOR - uint8_t j; - #endif //time to deal with this temp sensor switch(temp_sensors[i].temp_type) { #ifdef TEMP_MAX6675 @@ -173,25 +170,26 @@ void temp_sensor_tick() { #ifdef TEMP_THERMISTOR case TT_THERMISTOR: - - //Read current temperature - temp = analog_read(temp_sensors[i].temp_pin); - - //Calculate real temperature based on lookup table - for (j = 1; j < NUMTEMPS; j++) { - if (pgm_read_word(&(temptable[j][0])) > temp) { - // multiply by 4 because internal temp is stored as 14.2 fixed point - temp = pgm_read_word(&(temptable[j][1])) + (pgm_read_word(&(temptable[j][0])) - temp) * 4 * (pgm_read_word(&(temptable[j-1][1])) - pgm_read_word(&(temptable[j][1]))) / (pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0]))); - break; + do { + uint8_t j; + //Read current temperature + temp = analog_read(temp_sensors[i].temp_pin); + + //Calculate real temperature based on lookup table + for (j = 1; j < NUMTEMPS; j++) { + if (pgm_read_word(&(temptable[j][0])) > temp) { + // multiply by 4 because internal temp is stored as 14.2 fixed point + temp = pgm_read_word(&(temptable[j][1])) * 4 + (pgm_read_word(&(temptable[j][0])) - temp) * 4 * (pgm_read_word(&(temptable[j-1][1])) - pgm_read_word(&(temptable[j][1]))) / (pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0]))); + break; + } } + + //Clamp for overflows + if (j == NUMTEMPS) + temp = temptable[NUMTEMPS-1][1] * 4; + + temp_sensors_runtime[i].next_read_time = 0; } - - //Clamp for overflows - if (j == NUMTEMPS) - temp = temptable[NUMTEMPS-1][1]; - - temp_sensors_runtime[i].next_read_time = 0; - break; #endif /* TEMP_THERMISTOR */ From 773241399dbe86ea897d2e0229b3bbbfc605e3fb Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 27 Oct 2010 15:12:24 +1100 Subject: [PATCH 19/82] add pin definitions for non-arduino AVR users --- arduino_1280.h | 363 +++++++++++++++++++++++++++++++++++++++++++++ arduino_168_328p.h | 99 +++++++++++++ arduino_644.h | 132 +++++++++++++++++ 3 files changed, 594 insertions(+) diff --git a/arduino_1280.h b/arduino_1280.h index 47dd05b..3de03ca 100644 --- a/arduino_1280.h +++ b/arduino_1280.h @@ -384,3 +384,366 @@ pins #define AIO15_RPORT PINK #define AIO15_WPORT PORTK #define AIO15_DDR DDRK + +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA + +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB + +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC + +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD + +#define PE0_PIN PINE0 +#define PE0_RPORT PINE +#define PE0_WPORT PORTE +#define PE0_DDR DDRE +#define PE1_PIN PINE1 +#define PE1_RPORT PINE +#define PE1_WPORT PORTE +#define PE1_DDR DDRE +#define PE2_PIN PINE2 +#define PE2_RPORT PINE +#define PE2_WPORT PORTE +#define PE2_DDR DDRE +#define PE3_PIN PINE3 +#define PE3_RPORT PINE +#define PE3_WPORT PORTE +#define PE3_DDR DDRE +#define PE4_PIN PINE4 +#define PE4_RPORT PINE +#define PE4_WPORT PORTE +#define PE4_DDR DDRE +#define PE5_PIN PINE5 +#define PE5_RPORT PINE +#define PE5_WPORT PORTE +#define PE5_DDR DDRE +#define PE6_PIN PINE6 +#define PE6_RPORT PINE +#define PE6_WPORT PORTE +#define PE6_DDR DDRE +#define PE7_PIN PINE7 +#define PE7_RPORT PINE +#define PE7_WPORT PORTE +#define PE7_DDR DDRE + +#define PF0_PIN PINF0 +#define PF0_RPORT PINF +#define PF0_WPORT PORTF +#define PF0_DDR DDRF +#define PF1_PIN PINF1 +#define PF1_RPORT PINF +#define PF1_WPORT PORTF +#define PF1_DDR DDRF +#define PF2_PIN PINF2 +#define PF2_RPORT PINF +#define PF2_WPORT PORTF +#define PF2_DDR DDRF +#define PF3_PIN PINF3 +#define PF3_RPORT PINF +#define PF3_WPORT PORTF +#define PF3_DDR DDRF +#define PF4_PIN PINF4 +#define PF4_RPORT PINF +#define PF4_WPORT PORTF +#define PF4_DDR DDRF +#define PF5_PIN PINF5 +#define PF5_RPORT PINF +#define PF5_WPORT PORTF +#define PF5_DDR DDRF +#define PF6_PIN PINF6 +#define PF6_RPORT PINF +#define PF6_WPORT PORTF +#define PF6_DDR DDRF +#define PF7_PIN PINF7 +#define PF7_RPORT PINF +#define PF7_WPORT PORTF +#define PF7_DDR DDRF + +#define PG0_PIN PING0 +#define PG0_RPORT PING +#define PG0_WPORT PORTG +#define PG0_DDR DDRG +#define PG1_PIN PING1 +#define PG1_RPORT PING +#define PG1_WPORT PORTG +#define PG1_DDR DDRG +#define PG2_PIN PING2 +#define PG2_RPORT PING +#define PG2_WPORT PORTG +#define PG2_DDR DDRG +#define PG3_PIN PING3 +#define PG3_RPORT PING +#define PG3_WPORT PORTG +#define PG3_DDR DDRG +#define PG4_PIN PING4 +#define PG4_RPORT PING +#define PG4_WPORT PORTG +#define PG4_DDR DDRG +#define PG5_PIN PING5 +#define PG5_RPORT PING +#define PG5_WPORT PORTG +#define PG5_DDR DDRG +#define PG6_PIN PING6 +#define PG6_RPORT PING +#define PG6_WPORT PORTG +#define PG6_DDR DDRG +#define PG7_PIN PING7 +#define PG7_RPORT PING +#define PG7_WPORT PORTG +#define PG7_DDR DDRG + +#define PH0_PIN PINH0 +#define PH0_RPORT PINH +#define PH0_WPORT PORTH +#define PH0_DDR DDRH +#define PH1_PIN PINH1 +#define PH1_RPORT PINH +#define PH1_WPORT PORTH +#define PH1_DDR DDRH +#define PH2_PIN PINH2 +#define PH2_RPORT PINH +#define PH2_WPORT PORTH +#define PH2_DDR DDRH +#define PH3_PIN PINH3 +#define PH3_RPORT PINH +#define PH3_WPORT PORTH +#define PH3_DDR DDRH +#define PH4_PIN PINH4 +#define PH4_RPORT PINH +#define PH4_WPORT PORTH +#define PH4_DDR DDRH +#define PH5_PIN PINH5 +#define PH5_RPORT PINH +#define PH5_WPORT PORTH +#define PH5_DDR DDRH +#define PH6_PIN PINH6 +#define PH6_RPORT PINH +#define PH6_WPORT PORTH +#define PH6_DDR DDRH +#define PH7_PIN PINH7 +#define PH7_RPORT PINH +#define PH7_WPORT PORTH +#define PH7_DDR DDRH + +#define PJ0_PIN PINJ0 +#define PJ0_RPORT PINJ +#define PJ0_WPORT PORTJ +#define PJ0_DDR DDRJ +#define PJ1_PIN PINJ1 +#define PJ1_RPORT PINJ +#define PJ1_WPORT PORTJ +#define PJ1_DDR DDRJ +#define PJ2_PIN PINJ2 +#define PJ2_RPORT PINJ +#define PJ2_WPORT PORTJ +#define PJ2_DDR DDRJ +#define PJ3_PIN PINJ3 +#define PJ3_RPORT PINJ +#define PJ3_WPORT PORTJ +#define PJ3_DDR DDRJ +#define PJ4_PIN PINJ4 +#define PJ4_RPORT PINJ +#define PJ4_WPORT PORTJ +#define PJ4_DDR DDRJ +#define PJ5_PIN PINJ5 +#define PJ5_RPORT PINJ +#define PJ5_WPORT PORTJ +#define PJ5_DDR DDRJ +#define PJ6_PIN PINJ6 +#define PJ6_RPORT PINJ +#define PJ6_WPORT PORTJ +#define PJ6_DDR DDRJ +#define PJ7_PIN PINJ7 +#define PJ7_RPORT PINJ +#define PJ7_WPORT PORTJ +#define PJ7_DDR DDRJ + +#define PK0_PIN PINK0 +#define PK0_RPORT PINK +#define PK0_WPORT PORTK +#define PK0_DDR DDRK +#define PK1_PIN PINK1 +#define PK1_RPORT PINK +#define PK1_WPORT PORTK +#define PK1_DDR DDRK +#define PK2_PIN PINK2 +#define PK2_RPORT PINK +#define PK2_WPORT PORTK +#define PK2_DDR DDRK +#define PK3_PIN PINK3 +#define PK3_RPORT PINK +#define PK3_WPORT PORTK +#define PK3_DDR DDRK +#define PK4_PIN PINK4 +#define PK4_RPORT PINK +#define PK4_WPORT PORTK +#define PK4_DDR DDRK +#define PK5_PIN PINK5 +#define PK5_RPORT PINK +#define PK5_WPORT PORTK +#define PK5_DDR DDRK +#define PK6_PIN PINK6 +#define PK6_RPORT PINK +#define PK6_WPORT PORTK +#define PK6_DDR DDRK +#define PK7_PIN PINK7 +#define PK7_RPORT PINK +#define PK7_WPORT PORTK +#define PK7_DDR DDRK + +#define PL0_PIN PINL0 +#define PL0_RPORT PINL +#define PL0_WPORT PORTL +#define PL0_DDR DDRL +#define PL1_PIN PINL1 +#define PL1_RPORT PINL +#define PL1_WPORT PORTL +#define PL1_DDR DDRL +#define PL2_PIN PINL2 +#define PL2_RPORT PINL +#define PL2_WPORT PORTL +#define PL2_DDR DDRL +#define PL3_PIN PINL3 +#define PL3_RPORT PINL +#define PL3_WPORT PORTL +#define PL3_DDR DDRL +#define PL4_PIN PINL4 +#define PL4_RPORT PINL +#define PL4_WPORT PORTL +#define PL4_DDR DDRL +#define PL5_PIN PINL5 +#define PL5_RPORT PINL +#define PL5_WPORT PORTL +#define PL5_DDR DDRL +#define PL6_PIN PINL6 +#define PL6_RPORT PINL +#define PL6_WPORT PORTL +#define PL6_DDR DDRL +#define PL7_PIN PINL7 +#define PL7_RPORT PINL +#define PL7_WPORT PORTL +#define PL7_DDR DDRL diff --git a/arduino_168_328p.h b/arduino_168_328p.h index 5431c3e..9bc289b 100644 --- a/arduino_168_328p.h +++ b/arduino_168_328p.h @@ -125,3 +125,102 @@ pins #define AIO5_RPORT PINC #define AIO5_WPORT PORTC #define AIO5_DDR DDRC + +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB + +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC + +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD diff --git a/arduino_644.h b/arduino_644.h index 11d5aa7..9f1a4ab 100644 --- a/arduino_644.h +++ b/arduino_644.h @@ -229,3 +229,135 @@ pins #define AIO7_RPORT PINA #define AIO7_WPORT PORTA #define AIO7_DDR DDRA + +#define PA0_PIN PINA0 +#define PA0_RPORT PINA +#define PA0_WPORT PORTA +#define PA0_DDR DDRA +#define PA1_PIN PINA1 +#define PA1_RPORT PINA +#define PA1_WPORT PORTA +#define PA1_DDR DDRA +#define PA2_PIN PINA2 +#define PA2_RPORT PINA +#define PA2_WPORT PORTA +#define PA2_DDR DDRA +#define PA3_PIN PINA3 +#define PA3_RPORT PINA +#define PA3_WPORT PORTA +#define PA3_DDR DDRA +#define PA4_PIN PINA4 +#define PA4_RPORT PINA +#define PA4_WPORT PORTA +#define PA4_DDR DDRA +#define PA5_PIN PINA5 +#define PA5_RPORT PINA +#define PA5_WPORT PORTA +#define PA5_DDR DDRA +#define PA6_PIN PINA6 +#define PA6_RPORT PINA +#define PA6_WPORT PORTA +#define PA6_DDR DDRA +#define PA7_PIN PINA7 +#define PA7_RPORT PINA +#define PA7_WPORT PORTA +#define PA7_DDR DDRA + +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB + +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC + +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD From 95e7013dd68f07b62fdcee96fba060fe5156973d Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 28 Oct 2010 13:23:39 +1100 Subject: [PATCH 20/82] attempt to move heater PID to extruder controller board --- extruder/Makefile | 2 +- extruder/config.h.dist | 96 ++++++++++++++++++++++++++++++++++++------ extruder/debug.h | 1 + extruder/extruder.c | 62 ++++++--------------------- extruder/heater.c | 1 + extruder/heater.h | 1 + extruder/temp.c | 1 + extruder/temp.h | 1 + heater.c | 12 ++++-- mendel.c | 22 +++++++++- temp.c | 14 ++++-- temp.h | 2 + 12 files changed, 142 insertions(+), 73 deletions(-) create mode 120000 extruder/debug.h create mode 120000 extruder/heater.c create mode 120000 extruder/heater.h create mode 120000 extruder/temp.c create mode 120000 extruder/temp.h diff --git a/extruder/Makefile b/extruder/Makefile index dd18c29..5b4518b 100644 --- a/extruder/Makefile +++ b/extruder/Makefile @@ -31,7 +31,7 @@ PROGRAM = extruder -SOURCES = $(PROGRAM).c intercom.c delay.c analog.c watchdog.c +SOURCES = $(PROGRAM).c intercom.c delay.c analog.c watchdog.c heater.c temp.c ############################################################################## # # diff --git a/extruder/config.h.dist b/extruder/config.h.dist index b11dfb8..cd6d41a 100644 --- a/extruder/config.h.dist +++ b/extruder/config.h.dist @@ -26,15 +26,49 @@ #define TRIM_POT AIO0 #define TRIM_POT_CHANNEL 0 -//Debug LED will blink on RS485 transmission -#define DEBUG_LED DIO13 - //Read analog voltage from thermistor #define TEMP_PIN AIO3 #define TEMP_PIN_CHANNEL 3 #define REFERENCE REFERENCE_AVCC +#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL)) + +#define TEMP_THERMISTOR + +// extruder settings +#define TEMP_HYSTERESIS 20 +#define TEMP_RESIDENCY_TIME 60 + +#define NUM_TEMP_SENSORS 1 +#ifdef TEMP_C +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* If your temperature sensor has no associated heater, enter '255' as the * +* heater index. * +* * +* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * +* 255 * +* * +\***************************************************************************/ + +struct { + uint8_t temp_type; + uint8_t temp_pin; + + uint8_t heater_index; +} temp_sensors[NUM_TEMP_SENSORS] = +{ + { + TT_THERMISTOR, + PINC3, + 0 + } +}; +#endif + // list of PWM-able pins and corresponding timers // timer1 is used for step timing so don't use OC1A/OC1B (DIO9/DIO10) // OC0A DIO6 @@ -44,12 +78,46 @@ // OC2A DIO11 // OC2B DIO3 -#define HEATER_PIN DIO11 -#define HEATER_PWM OCR2A +#define TH_COUNT 8 +#define PID_SCALE 1024L -#define BED_PIN DIO12 +#define NUM_HEATERS 2 +#ifdef HEATER_C +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* For the atmega168/328, timer/pin mappings are as follows * +* * +* OCR0A - PD6 * +* OCR0B - PD5 * +* OCR2A - PB3 * +* OCR2B - PD3 * +* * +\***************************************************************************/ +struct { + volatile uint8_t *heater_port; + uint8_t heater_pin; + volatile uint8_t *heater_pwm; +} heaters[NUM_HEATERS] = +{ + { + &PORTD, + PIND6, + &OCR0A + }, + { + &PORTB, + PINB4, + 0 + } +}; +#endif -#define ANALOG_MASK (MASK(TRIM_POT_CHANNEL) | MASK(TEMP_PIN_CHANNEL)) +// #define HEATER_PIN DIO11 +// #define HEATER_PWM OCR2A +// +// #define BED_PIN DIO12 /* Intercom @@ -68,12 +136,12 @@ Heater */ -#ifdef HEATER_PWM - #define enable_heater() do { TCCR2A |= MASK(COM2A1); } while (0) - #define disable_heater() do { TCCR2A &= ~MASK(COM2A1); } while (0) -#else - #define enable_heater() WRITE(HEATER_PIN, 1) - #define disable_heater() WRITE(HEATER_PIN, 0) -#endif +// #ifdef HEATER_PWM +// #define enable_heater() do { TCCR2A |= MASK(COM2A1); } while (0) +// #define disable_heater() do { TCCR2A &= ~MASK(COM2A1); } while (0) +// #else +// #define enable_heater() WRITE(HEATER_PIN, 1) +// #define disable_heater() WRITE(HEATER_PIN, 0) +// #endif #endif /* _CONFIG_H */ diff --git a/extruder/debug.h b/extruder/debug.h new file mode 120000 index 0000000..845c7cc --- /dev/null +++ b/extruder/debug.h @@ -0,0 +1 @@ +../debug.h \ No newline at end of file diff --git a/extruder/extruder.c b/extruder/extruder.c index 7d11b70..cc4bbb0 100644 --- a/extruder/extruder.c +++ b/extruder/extruder.c @@ -7,33 +7,11 @@ #include "analog.h" #include "config.h" #include "watchdog.h" +#include "heater.h" +#include "temp.h" static uint8_t motor_pwm; -#define NUMTEMPS 20 -short temptable[NUMTEMPS][2] = { - {1, 841}, - {54, 255}, - {107, 209}, - {160, 184}, - {213, 166}, - {266, 153}, - {319, 142}, - {372, 132}, - {425, 124}, - {478, 116}, - {531, 108}, - {584, 101}, - {637, 93}, - {690, 86}, - {743, 78}, - {796, 70}, - {849, 61}, - {902, 50}, - {955, 34}, - {1008, 3} -}; - void io_init(void) { // setup I/O pins WRITE(DEBUG_LED, 0); SET_OUTPUT(DEBUG_LED); @@ -60,14 +38,14 @@ void io_init(void) { WRITE(BED_PIN, 0); SET_OUTPUT(BED_PIN); #endif - #if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM) +// #if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM) // setup PWM timer: fast PWM, no prescaler TCCR2A = MASK(WGM21) | MASK(WGM20); TCCR2B = MASK(CS22); TIMSK2 = 0; OCR2A = 0; OCR2B = 0; - #endif +// #endif #if defined(H1E_PWM) && defined(H2E_PWM) TCCR0A = MASK(WGM01) | MASK(WGM00); @@ -174,6 +152,12 @@ void init(void) { // set up inputs and outputs io_init(); + // temp sensor + temp_init(); + + // heater + heater_init(); + // set up extruder motor driver motor_init(); @@ -187,9 +171,6 @@ void init(void) { int main (void) { - static uint8_t i; - static uint16_t raw_temp; - init(); enable_heater(); @@ -204,26 +185,9 @@ int main (void) //Read motor PWM motor_pwm = analog_read(TRIM_POT_CHANNEL) >> 2; - //Read current temperature - raw_temp = analog_read(TEMP_PIN_CHANNEL); + temp_sensor_tick(); - //Calculate real temperature based on lookup table - for (i = 1; i < NUMTEMPS; i++) { - if (temptable[i][0] > raw_temp) { - raw_temp = temptable[i][1] + - (temptable[i][0] - raw_temp) * (temptable[i-1][1] - temptable[i][1]) / (temptable[i][0] - temptable[i-1][0]); - - break; - } - } - - //Clamp for overflows - if (i == NUMTEMPS) raw_temp = temptable[NUMTEMPS-1][1]; - if (raw_temp > 255) raw_temp = 255; - - //Update the intercom values - update_send_cmd(raw_temp); - - HEATER_PWM = get_read_cmd(); + update_send_cmd(temp_get(0) >> 2); + temp_set(0, get_read_cmd()); } } diff --git a/extruder/heater.c b/extruder/heater.c new file mode 120000 index 0000000..acfa7db --- /dev/null +++ b/extruder/heater.c @@ -0,0 +1 @@ +../heater.c \ No newline at end of file diff --git a/extruder/heater.h b/extruder/heater.h new file mode 120000 index 0000000..22c6069 --- /dev/null +++ b/extruder/heater.h @@ -0,0 +1 @@ +../heater.h \ No newline at end of file diff --git a/extruder/temp.c b/extruder/temp.c new file mode 120000 index 0000000..f59d719 --- /dev/null +++ b/extruder/temp.c @@ -0,0 +1 @@ +../temp.c \ No newline at end of file diff --git a/extruder/temp.h b/extruder/temp.h new file mode 120000 index 0000000..5f7682d --- /dev/null +++ b/extruder/temp.h @@ -0,0 +1 @@ +../temp.h \ No newline at end of file diff --git a/heater.c b/heater.c index 68c6798..6c35b39 100644 --- a/heater.c +++ b/heater.c @@ -4,9 +4,11 @@ #include #include "arduino.h" -#include "timer.h" +// #include "timer.h" #include "debug.h" -#include "sersendf.h" +#ifdef DEBUG + #include "sersendf.h" +#endif #define HEATER_C #include "config.h" @@ -124,10 +126,12 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { heaters_runtime[h].pid_output = 0; else heaters_runtime[h].pid_output = pid_output_intermed & 0xFF; - + + #ifdef DEBUG if (debug_flags & DEBUG_PID) sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heaters_runtime[h].heater_p, heaters_pid[h].p_factor, (int32_t) heaters_runtime[h].heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heaters_runtime[h].heater_d, heaters_pid[h].d_factor, (int32_t) heaters_runtime[h].heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, heaters_runtime[h].pid_output); - + #endif + heater_set(h, heaters_runtime[h].pid_output); } diff --git a/mendel.c b/mendel.c index 76e8305..e1b2af7 100644 --- a/mendel.c +++ b/mendel.c @@ -35,15 +35,33 @@ void io_init(void) { WRITE(X_STEP_PIN, 0); SET_OUTPUT(X_STEP_PIN); WRITE(X_DIR_PIN, 0); SET_OUTPUT(X_DIR_PIN); WRITE(X_MIN_PIN, 1); SET_INPUT(X_MIN_PIN); + #ifdef X_MAX_PIN + WRITE(X_MAX_PIN, 1); SET_INPUT(X_MAX_PIN); + #endif + #ifdef X_ENABLE_PIN + WRITE(X_ENABLE_PIN, 1); SET_OUTPUT(X_ENABLE_PIN); + #endif WRITE(Y_STEP_PIN, 0); SET_OUTPUT(Y_STEP_PIN); WRITE(Y_DIR_PIN, 0); SET_OUTPUT(Y_DIR_PIN); WRITE(Y_MIN_PIN, 1); SET_INPUT(Y_MIN_PIN); - + #ifdef Y_MAX_PIN + WRITE(Y_MAX_PIN, 1); SET_INPUT(Y_MAX_PIN); + #endif + #ifdef Y_ENABLE_PIN + WRITE(Y_ENABLE_PIN, 1); SET_OUTPUT(Y_ENABLE_PIN); + #endif + WRITE(Z_STEP_PIN, 0); SET_OUTPUT(Z_STEP_PIN); WRITE(Z_DIR_PIN, 0); SET_OUTPUT(Z_DIR_PIN); WRITE(Z_MIN_PIN, 1); SET_INPUT(Z_MIN_PIN); - + #ifdef Z_MAX_PIN + WRITE(Z_MAX_PIN, 1); SET_INPUT(Z_MAX_PIN); + #endif + #ifdef Z_ENABLE_PIN + WRITE(Z_ENABLE_PIN, 1); SET_OUTPUT(Z_ENABLE_PIN); + #endif + WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN); WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN); diff --git a/temp.c b/temp.c index 92edd3c..dca7a4f 100644 --- a/temp.c +++ b/temp.c @@ -5,9 +5,11 @@ #include #include "arduino.h" -#include "timer.h" +// #include "timer.h" #include "debug.h" -#include "sersendf.h" +#ifndef EXTRUDER + #include "sersendf.h" +#endif #include "heater.h" #ifdef GEN3 #include "intercom.h" @@ -189,7 +191,7 @@ void temp_sensor_tick() { temp = temptable[NUMTEMPS-1][1] * 4; temp_sensors_runtime[i].next_read_time = 0; - } + } while (0); break; #endif /* TEMP_THERMISTOR */ @@ -253,6 +255,11 @@ void temp_set(uint8_t index, uint16_t temperature) { #endif } +uint16_t temp_get(uint8_t index) { + return temp_sensors_runtime[index].last_read_temp; +} + +#ifndef EXTRUDER void temp_print(uint8_t index) { uint8_t c = 0; @@ -260,3 +267,4 @@ void temp_print(uint8_t index) { sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c); } +#endif diff --git a/temp.h b/temp.h index c912760..b00ee95 100644 --- a/temp.h +++ b/temp.h @@ -20,6 +20,8 @@ void temp_sensor_tick(void); uint8_t temp_achieved(void); void temp_set(uint8_t index, uint16_t temperature); +uint16_t temp_get(uint8_t index); + void temp_print(uint8_t index); uint16_t temp_read(uint8_t index); From 6427e8a6cfa65e8283f7e9c105fc39f8fd23482f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 16:44:11 +1100 Subject: [PATCH 21/82] temp uses delay in some configurations --- temp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temp.c b/temp.c index dca7a4f..9eec470 100644 --- a/temp.c +++ b/temp.c @@ -5,7 +5,7 @@ #include #include "arduino.h" -// #include "timer.h" +#include "delay.h" #include "debug.h" #ifndef EXTRUDER #include "sersendf.h" From c9f9464a26790f034220ece1726db7c70e4a78df Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 16:44:35 +1100 Subject: [PATCH 22/82] fix case where ANALOG_MASK is zero --- analog.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/analog.c b/analog.c index 162b429..f04af5c 100644 --- a/analog.c +++ b/analog.c @@ -9,10 +9,7 @@ uint8_t adc_running_mask, adc_counter; -#if ANALOG_MASK & 1 - #define ANALOG_START 0 - #define ANALOG_START_MASK 1 -#elif ANALOG_MASK & 2 +#if ANALOG_MASK & 2 #define ANALOG_START 1 #define ANALOG_START_MASK 2 #elif ANALOG_MASK & 4 @@ -33,6 +30,10 @@ uint8_t adc_running_mask, adc_counter; #elif ANALOG_MASK & 128 #define ANALOG_START 7 #define ANALOG_START_MASK 128 +#else + // ANALOG_MASK == 1 or 0, either way defines are the same except they're not used if ANALOG_MASK == 0 + #define ANALOG_START 0 + #define ANALOG_START_MASK 1 #endif volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss"))); From 162a7b2442c54b6a40b2e14c3d1551954dafb2e3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 16:44:53 +1100 Subject: [PATCH 23/82] %c is used in print_queue, enable it --- sersendf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sersendf.c b/sersendf.c index 99c184e..13d4eae 100644 --- a/sersendf.c +++ b/sersendf.c @@ -96,6 +96,10 @@ void sersendf_P(PGM_P format, ...) { serwrite_int16(va_arg(args, int16_t)); j = 0; break; + case 'c': + serial_writechar(va_arg(args, uint16_t)); + j = 0; + break; /* case 'x': serial_writestr_P(str_ox); if (j == 4) @@ -106,8 +110,6 @@ void sersendf_P(PGM_P format, ...) { serwrite_hex16(va_arg(args, uint16_t)); j = 0; break; - case 'c': - serial_writechar(va_arg(args, uint16_t)); case 'p': serwrite_hex16(va_arg(args, uint16_t)); default: From d57dc22c0462f0d39e8869f00f35ac9fd47ef9d3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 16:45:34 +1100 Subject: [PATCH 24/82] initialise PWM properly --- heater.c | 48 ++++++++++++++++++++++++++++++++++++------------ mendel.c | 5 +++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/heater.c b/heater.c index 6c35b39..94991cf 100644 --- a/heater.c +++ b/heater.c @@ -46,18 +46,40 @@ typedef struct { int16_t EE_i_limit; } EE_factor; -EE_factor EEMEM EE_factors[NUM_HEATERS]; +EE_factor EEMEM EE_factors[NUM_HEATERS] = { + { + DEFAULT_P, + DEFAULT_I, + DEFAULT_D, + DEFAULT_I_LIMIT + } +}; void heater_init() { #if NUM_HEATERS > 0 uint8_t i; // setup pins for (i = 0; i < NUM_HEATERS; i++) { - *(heaters[i].heater_port) &= ~heaters[i].heater_pin; + *(heaters[i].heater_port) &= ~MASK(heaters[i].heater_pin); // DDR is always 1 address below PORT. ugly code but saves ram and an extra field in heaters[] which will never be used anywhere but here - *((volatile uint8_t *) (heaters[i].heater_port - 1)) |= heaters[i].heater_pin; - if (heaters[i].heater_pwm) + *((volatile uint8_t *) (heaters[i].heater_port - 1)) |= MASK(heaters[i].heater_pin); + if (heaters[i].heater_pwm) { *heaters[i].heater_pwm = 0; + switch((uint16_t) heaters[i].heater_pwm) { + case (uint16_t) &OCR0A: + TCCR0A |= MASK(COM0A1); + break; + case (uint16_t) &OCR0B: + TCCR0A |= MASK(COM0B1); + break; + case (uint16_t) &OCR2A: + TCCR2A |= MASK(COM2A1); + break; + case (uint16_t) &OCR2B: + TCCR2A |= MASK(COM2B1); + break; + } + } } // read factors from eeprom @@ -112,11 +134,11 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { // combine factors int32_t pid_output_intermed = ( - ( - (((int32_t) heaters_runtime[h].heater_p) * heaters_pid[h].p_factor) + - (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + - (((int32_t) heaters_runtime[h].heater_d) * heaters_pid[h].d_factor) - ) / PID_SCALE + ( + (((int32_t) heaters_runtime[h].heater_p) * heaters_pid[h].p_factor) + + (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + + (((int32_t) heaters_runtime[h].heater_d) * heaters_pid[h].d_factor) + ) / PID_SCALE ); // rebase and limit factors @@ -138,13 +160,15 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { void heater_set(uint8_t index, uint8_t value) { #if NUM_HEATERS > 0 if (heaters[index].heater_pwm) { - *heaters[index].heater_pwm = value; + *(heaters[index].heater_pwm) = value; + if (debug_flags & DEBUG_PID) + sersendf_P(PSTR("PWM{%u = %u}\n"), index, OCR0A); } else { if (value >= 8) - *heaters[index].heater_port |= MASK(heaters[index].heater_pin); + *(heaters[index].heater_port) |= MASK(heaters[index].heater_pin); else - *heaters[index].heater_port &= ~MASK(heaters[index].heater_pin); + *(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin); } #endif } diff --git a/mendel.c b/mendel.c index e1b2af7..0aa5de5 100644 --- a/mendel.c +++ b/mendel.c @@ -17,6 +17,7 @@ #include "heater.h" #include "analog.h" #include "pinio.h" +#include "arduino.h" void io_init(void) { // disable modules we don't use @@ -65,12 +66,12 @@ void io_init(void) { WRITE(E_STEP_PIN, 0); SET_OUTPUT(E_STEP_PIN); WRITE(E_DIR_PIN, 0); SET_OUTPUT(E_DIR_PIN); - // setup PWM timer: fast PWM, no prescaler + // setup PWM timers: fast PWM, no prescaler TCCR0A = MASK(WGM01) | MASK(WGM00); TCCR0B = MASK(CS00); TIMSK0 = 0; OCR0A = 0; - OCR0B = 255; + OCR0B = 0; TCCR2A = MASK(WGM21) | MASK(WGM20); TCCR2B = MASK(CS20); From d43adfd72909cbe59b0d9d7ecebccf9141c1fdf3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 16:46:56 +1100 Subject: [PATCH 25/82] new protocol support for host-side debugging functions --- func.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/func.sh b/func.sh index 92788f1..8fdb7da 100755 --- a/func.sh +++ b/func.sh @@ -108,14 +108,12 @@ mendel_cmd() { local RSC=0 local cmd="$*" echo "$cmd" >&3; - while [ "$REPLY" != "OK" ] && [ "$REPLY" != "ok" ] + local REPLY="" + while ! [[ "$REPLY" =~ ^OK ]] && ! [[ "$REPLY" =~ ^ok ]] do read -u 3 - if [ "$REPLY" != "OK" ] && [ "$REPLY" != "ok" ] - then - echo "$REPLY" - fi - if [[ "$REPLY" =~ ^RESEND ]] + echo "${REPLY##ok }" + if [[ "$REPLY" =~ ^RESEND ]] || [[ "$REPLY" =~ ^rs ]] then if [ "$RSC" -le 3 ] then @@ -137,11 +135,12 @@ mendel_cmd_hr() { local RSC=0 echo "$cmd" >&3 echo "S> $cmd" - while [ "$REPLY" != "OK" ] && [ "$REPLY" != "ok" ] + local REPLY="" + while ! [[ "$REPLY" =~ ^OK ]] && ! [[ "$REPLY" =~ ^ok ]] do read -u 3 echo " Date: Sun, 7 Nov 2010 16:47:35 +1100 Subject: [PATCH 26/82] use sersendf_P more --- gcode_process.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index 243bef5..3eff9f0 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -14,6 +14,7 @@ #include "timer.h" #include "sersendf.h" #include "pinio.h" +#include "debug.h" /**************************************************************************** * * @@ -387,20 +388,22 @@ void process_gcode_command() { // DEBUG: write arbitrary memory locatiom case 254: - serwrite_hex8(next_target.S); - serial_writechar(':'); - serwrite_hex8(*(volatile uint8_t *)(next_target.S)); - serial_writestr_P(PSTR("->")); - serwrite_hex8(next_target.P); - serial_writechar('\n'); +// serwrite_hex8(next_target.S); +// serial_writechar(':'); +// serwrite_hex8(*(volatile uint8_t *)(next_target.S)); +// serial_writestr_P(PSTR("->")); +// serwrite_hex8(next_target.P); +// serial_writechar('\n'); + sersendf_P(PSTR("%x:%x->%x\n"), next_target.S, *(volatile uint8_t *)(next_target.S), next_target.P); (*(volatile uint8_t *)(next_target.S)) = next_target.P; break; #endif /* DEBUG */ // unknown mcode: spit an error default: - serial_writestr_P(PSTR("E: Bad M-code ")); +/* serial_writestr_P(PSTR("E: Bad M-code ")); serwrite_uint8(next_target.M); - serial_writechar('\n'); + serial_writechar('\n');*/ + sersendf_P(PSTR("E: Bad M-code %d\n"), next_target.M); } } } From be92a09db2dff56bc53d3de884c0010cf88bcd6f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 17:12:13 +1100 Subject: [PATCH 27/82] always set timer after step as timer works differently now --- dda.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dda.c b/dda.c index c35e0bf..afa7312 100644 --- a/dda.c +++ b/dda.c @@ -491,11 +491,9 @@ void dda_step(DDA *dda) { ) { dda->c = (int32_t) dda->c - ((int32_t) (dda->c * 2) / dda->n); dda->n += 4; - setTimer(dda->c >> 8); } else if (dda->c != dda->end_c) { dda->c = dda->end_c; - setTimer(dda->c >> 8); } // else we are already at target speed } @@ -525,18 +523,17 @@ void dda_step(DDA *dda) { dda->ramp_state = RAMP_MAX; dda->ramp_steps = dda->total_steps - dda->step_no; } - setTimer(dda->c >> 8); break; } dda->step_no++; #endif - + if (did_step) { // we stepped, reset timeout steptimeout = 0; - // if we could do anything at all, we're still running - // otherwise, must have finished + // if we could do anything at all, we're still running + // otherwise, must have finished } else { dda->live = 0; @@ -546,7 +543,8 @@ void dda_step(DDA *dda) { // in theory, we *could* update F every step, but that would require a divide in interrupt context which should be avoided if at all possible current_position.F = dda->endpoint.F; } - + setTimer(dda->c >> 8); + // turn off step outputs, hopefully they've been on long enough by now to register with the drivers // if not, too bad. or insert a (very!) small delay here, or fire up a spare timer or something. // we also hope that we don't step before the drivers register the low- limit maximum speed if you think this is a problem. From b5e92da9406827f6e6af2a2f47db863616292806 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 7 Nov 2010 17:12:41 +1100 Subject: [PATCH 28/82] new movebuffer format with acceleration_ramping enabled --- func.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/func.sh b/func.sh index 8fdb7da..cc2e469 100755 --- a/func.sh +++ b/func.sh @@ -252,7 +252,7 @@ mendel_readsym_mb() { local mbtail=$(mendel_readsym mb_tail) perl - <<'ENDPERL' -- $val $mbhead $mbtail $i = -1; - @a = qw/eX 4 eY 4 eZ 4 eE 4 eF 4 flags 9 dX 12 dY 4 dZ 4 dE 4 cX 12 cY 4 cZ 4 cE 4 ts 12 c 12 ec 4 n 4/; + @a = qw/eX 4 eY 4 eZ 4 eE 4 eF 4 flags 9 dX 12 dY 4 dZ 4 dE 4 cX 12 cY 4 cZ 4 cE 4 ts 12 c 12 rs 4 sn 4 cm 4 n 4 rs 1/; $c = 0; $c = 1234567; while (length $ARGV[1]) { From a60a15096d7c40fa23a0599d207127a3ebcf4934 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:25:01 +1100 Subject: [PATCH 29/82] initialize PWM for atmega1280 --- mendel.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/mendel.c b/mendel.c index 0aa5de5..0e5d0cc 100644 --- a/mendel.c +++ b/mendel.c @@ -23,11 +23,11 @@ void io_init(void) { // disable modules we don't use #ifdef PRR PRR = MASK(PRTWI) | MASK(PRADC) | MASK(PRSPI); - #endif - #ifdef PRR0 + #elif defined PRR0 PRR0 = MASK(PRTWI) | MASK(PRADC) | MASK(PRSPI); #ifdef PRR1 - PRR1 = 0xFF; + // don't use USART2 or USART3- leave USART1 for GEN3 and derivatives + PRR1 = MASK(PRUSART3) | MASK(PRUSART2); #endif #endif ACSR = MASK(ACD); @@ -79,6 +79,30 @@ void io_init(void) { OCR2A = 0; OCR2B = 0; + #ifdef TCCR3A + TCCR3A = MASK(WGM31) | MASK(WGM30); + TCCR3B = MASK(CS30); + TIMSK3 = 0; + OCR3A = 0; + OCR3B = 0; + #endif + + #ifdef TCCR4A + TCCR4A = MASK(WGM41) | MASK(WGM40); + TCCR4B = MASK(CS40); + TIMSK4 = 0; + OCR4A = 0; + OCR4B = 0; + #endif + + #ifdef TCCR5A + TCCR5A = MASK(WGM51) | MASK(WGM50); + TCCR5B = MASK(CS50); + TIMSK5 = 0; + OCR5A = 0; + OCR5B = 0; + #endif + #ifdef STEPPER_ENABLE_PIN power_off(); #endif From 3e22da35ae073ce70851fa83f3eb39055badceab Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:26:06 +1100 Subject: [PATCH 30/82] add M135- set heater, also remove superfluous code and some whitespace changes --- gcode_process.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index 3eff9f0..a28918e 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -271,57 +271,58 @@ void process_gcode_command() { // M130- heater P factor case 130: if (next_target.seen_S) -// p_factor = next_target.S; pid_set_p(next_target.P, next_target.S); break; // M131- heater I factor case 131: if (next_target.seen_S) -// i_factor = next_target.S; pid_set_i(next_target.P, next_target.S); break; // M132- heater D factor case 132: if (next_target.seen_S) -// d_factor = next_target.S; pid_set_d(next_target.P, next_target.S); break; // M133- heater I limit case 133: if (next_target.seen_S) -// i_limit = next_target.S; pid_set_i_limit(next_target.P, next_target.S); break; // M134- save PID settings to eeprom case 134: heater_save_settings(); break; + // M135- set heater output + case 135: + if (next_target.seen_S) + heater_set(next_target.P, next_target.S); + break; #endif /* NUM_HEATERS > 0 */ // M190- power on case 190: power_on(); #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 0); + WRITE(X_ENABLE_PIN, 0); #endif #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 0); + WRITE(Y_ENABLE_PIN, 0); #endif #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 0); + WRITE(Z_ENABLE_PIN, 0); #endif steptimeout = 0; break; // M191- power off case 191: #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 1); + WRITE(X_ENABLE_PIN, 1); #endif #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 1); + WRITE(Y_ENABLE_PIN, 1); #endif #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 1); + WRITE(Z_ENABLE_PIN, 1); #endif power_off(); break; From be0a0134c8b6917e023a47ec043839584eb02081 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:26:33 +1100 Subject: [PATCH 31/82] check DEBUG flag before pulling in sersendf_P --- heater.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/heater.c b/heater.c index 94991cf..a5b2dd6 100644 --- a/heater.c +++ b/heater.c @@ -161,8 +161,10 @@ void heater_set(uint8_t index, uint8_t value) { #if NUM_HEATERS > 0 if (heaters[index].heater_pwm) { *(heaters[index].heater_pwm) = value; + #ifdef DEBUG if (debug_flags & DEBUG_PID) sersendf_P(PSTR("PWM{%u = %u}\n"), index, OCR0A); + #endif } else { if (value >= 8) From a064ea8e372b6a08c3afad95d6ee1daa8915fa67 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:27:34 +1100 Subject: [PATCH 32/82] major rearranging of config.h.dist, hopefully easier to follow for first-timers --- config.h.dist | 431 +++++++++++++++++++++++++++++--------------------- 1 file changed, 255 insertions(+), 176 deletions(-) diff --git a/config.h.dist b/config.h.dist index a9ebbbd..fb11c23 100644 --- a/config.h.dist +++ b/config.h.dist @@ -1,6 +1,25 @@ #ifndef _CONFIG_H #define _CONFIG_H +/* + CONTENTS + + 1. Mechanical/Hardware + 2. Acceleration settings + 3. Pinouts + 4. Temperature sensors + 5. Heaters + 6. Communication options + 7. Miscellaneous + 8. Appendix A - PWMable pins and mappings +*/ + +/***************************************************************************\ +* * +* 1. MECHANICAL/HARDWARE * +* * +\***************************************************************************/ + /* Values reflecting the gearing of your machine. All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-) @@ -17,6 +36,7 @@ // http://blog.arcol.hu/?p=157 may help with this next one #define STEPS_PER_MM_E 320.000 + /* Values depending on the capabilities of your stepper motors and other mechanics. All numbers are integers, no decimals allowed. @@ -34,13 +54,17 @@ #define SEARCH_FEEDRATE_Z 50 #define SEARCH_FEEDRATE_E 50 -// extruder settings -#define TEMP_HYSTERESIS 20 -#define TEMP_RESIDENCY_TIME 60 - // this is how many steps to suck back the filament by when we stop. set to zero to disable #define E_STARTSTOP_STEPS 20 + +/***************************************************************************\ +* * +* 2. ACCELERATION * +* * +\***************************************************************************/ + + /* acceleration, reprap style. Each movement starts at the speed of the previous command and accelerates or decelerates linearly to reach target speed at the end of the movement. @@ -62,139 +86,50 @@ #ifdef ACCELERATION_REPRAP #ifdef ACCELERATION_RAMPING - #error Cant use ACCELERATION_REPRAP and ACCELERATION_RAMPING together. + #error Can't use ACCELERATION_REPRAP and ACCELERATION_RAMPING together. #endif #endif -// which temperature sensor are you using? -// #define TEMP_MAX6675 -// #define TEMP_THERMISTOR -// #define TEMP_AD595 -#define NUM_TEMP_SENSORS 1 -#ifdef TEMP_C /***************************************************************************\ * * -* Fill in the following struct according to your hardware * -* * -* If your temperature sensor has no associated heater, enter '255' as the * -* heater index. * -* * -* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * -* 255 * +* 3. PINOUTS * * * \***************************************************************************/ -struct { - uint8_t temp_type; - uint8_t temp_pin; - - uint8_t heater_index; -} temp_sensors[NUM_TEMP_SENSORS] = -{ - { - TT_INTERCOM, - 0, - 0 - } -}; -#endif - -#define NUM_HEATERS 0 -#ifdef HEATER_C -/***************************************************************************\ -* * -* Fill in the following struct according to your hardware * -* * -* For the atmega168/328, timer/pin mappings are as follows * -* * -* OCR0A - PD6 * -* OCR0B - PD5 * -* OCR2A - PB3 * -* OCR2B - PD3 * -* * -\***************************************************************************/ -struct { - volatile uint8_t *heater_port; - uint8_t heater_pin; - volatile uint8_t *heater_pwm; -} heaters[NUM_HEATERS]/* = -{ - { - &PORTD, - PIND6, - &OCR0A - } -}*/; -#endif - -// temperature history count. higher values make PID derivative term more stable at the expense of reaction time -#define TH_COUNT 8 - -// if you selected thermistor or AD595, what pin is it on? -#define TEMP_PIN_CHANNEL AIO0_PIN -#define ANALOG_MASK MASK(TEMP_PIN_CHANNEL) - -/* - Firmware build options -*/ - -/* - RepRap Host changes it's communications protocol from time to time and intentionally avoids backwards compatibility. Set this to the date the source code of your Host was fetched from RepRap's repository, which is likely also the build date. - See the discussion on the reprap-dev mailing list from 11 Oct. 2010. - - Undefine it for best human readability, set it to an old date for compatibility with hosts before August 2010 -*/ -// #define REPRAP_HOST_COMPATIBILITY 19750101 -#define REPRAP_HOST_COMPATIBILITY 20100806 -// #define REPRAP_HOST_COMPATIBILITY - - -// this option makes the step interrupt interruptible. -// this should help immensely with dropped serial characters, but may also make debugging infuriating due to the complexities arising from nested interrupts -#define STEP_INTERRUPT_INTERRUPTIBLE 1 - -/* - Xon/Xoff flow control. - Redundant when using RepRap Host for sending GCode, but mandatory when sending GCode files with a plain terminal emulator, like GtkTerm (Linux), CoolTerm (Mac) or HyperTerminal (Windows). - Can also be set in Makefile -*/ -// #define XONXOFF - -/* - move buffer size, in number of moves - note that each move takes a fair chunk of ram (69 bytes as of this writing) so don't make the buffer too big - a bigger serial readbuffer may help more than increasing this unless your gcodes are more than 70 characters long on average. - however, a larger movebuffer will probably help with lots of short consecutive moves, as each move takes a bunch of math (hence time) to set up so a longer buffer allows more of the math to be done during preceding longer moves -*/ -#define MOVEBUFFER_SIZE 8 - -/* - FiveD on Arduino implements a watchdog, which has to be reset every 250ms or it will reboot the controller. As rebooting (and letting the GCode sending application trying to continue the build with a then different Home point) is probably even worse than just hanging, and there is no better restore code in place, this is disabled for now. -*/ -// #define USE_WATCHDOG - -/* - analog subsystem stuff - REFERENCE - which analog reference to use. see analog.h for choices - ANALOG_MASK - which analog inputs we will be using, bitmask. eg; #define ANALOG_MASK MASK(AIO0_PIN) | MASK(3) for AIN0 and AIN3 -*/ -#define REFERENCE REFERENCE_AVCC - -#ifndef ANALOG_MASK -#define ANALOG_MASK 0 -#endif /* Machine Pin Definitions - - make sure to avoid duplicate usage of a pin - - comment out pins not in use, as this drops the corresponding code and makes operations faster */ #include "arduino.h" -#ifdef GEN3 +#ifndef GEN3 + /* + user defined pins + adjust to suit your electronics, + or adjust your electronics to suit this + */ + + #define X_STEP_PIN AIO0 + #define X_DIR_PIN AIO1 + #define X_MIN_PIN AIO2 + + #define Y_STEP_PIN AIO3 + #define Y_DIR_PIN AIO4 + #define Y_MIN_PIN AIO5 + + #define Z_STEP_PIN DIO2 + #define Z_DIR_PIN DIO3 + #define Z_MIN_PIN DIO4 + + #define E_STEP_PIN DIO7 + #define E_DIR_PIN DIO8 + + #define PS_ON_PIN DIO9 +#else // this is official reprap motherboard pinout #define TX_ENABLE_PIN DIO12 #define RX_ENABLE_PIN DIO13 @@ -222,67 +157,211 @@ struct { #define SD_CARD_DETECT DIO2 #define SD_WRITE_PROTECT DIO3 -#else - /* - user defined pins - adjust to suit your electronics, - or adjust your electronics to suit this - */ - - #define X_STEP_PIN AIO0 - #define X_DIR_PIN AIO1 - #define X_MIN_PIN AIO2 - - #define Y_STEP_PIN AIO3 - #define Y_DIR_PIN AIO4 - #define Y_MIN_PIN AIO5 - - #define Z_STEP_PIN DIO2 - #define Z_DIR_PIN DIO3 - #define Z_MIN_PIN DIO4 - - #define E_STEP_PIN DIO7 - #define E_DIR_PIN DIO8 - - #define PS_ON_PIN DIO9 #endif -/** - * list of PWM-able pins and corresponding timers - * timer1 is used for step timing so don't use OC1A/OC1B - * - * For Arduino Diecimila/Duemilanove/UNO - * Don't use OC1A/OC1B (DIO9/DIO10) - * - * OC0A DIO6 - * OC0B DIO5 - * OC1A DIO9 - * OC1B DIO10 - * OC2A DIO11 - * OC2B DIO3 - * - * For Arduino Mega - * Don't use OC1A/OC1B (DIO11/DIO12) - * - * OC0A DIO13 - * OC0B DIO4 - * OC1A DIO11 - * OC1B DIO12 - * OC2A DIO10 - * OC2B DIO9 - * OC3A DIO5 - * OC3B DIO2 - * OC3C DIO3 - * OC4A DIO6 - * OC4B DIO7 - * OC4C DIO8 - * OC5A DIO46 - * OC5B DIO45 - * OC5C DIO44 - * - */ +/***************************************************************************\ +* * +* 4. TEMPERATURE SENSORS * +* * +\***************************************************************************/ + +/* + TEMP_HYSTERESIS: actual temperature must be target +/- hysteresis before target temperature can be achieved + TEMP_RESIDENCY_TIME: actual temperature must be close to target for this long before target is achieved + + temperature is "achieved" for purposes of M109 and friends when actual temperature is within [hysteresis] of target for [residency] seconds +*/ +#define TEMP_HYSTERESIS 5 +#define TEMP_RESIDENCY_TIME 60 + +// which temperature sensors are you using? (intercom is the gen3-style separate extruder board) +// #define TEMP_MAX6675 +// #define TEMP_THERMISTOR +// #define TEMP_AD595 +// #define TEMP_INTERCOM + +// if you selected thermistor or AD595, what pin is it on? (this value only used to fill ANALOG_MASK for you) +#define TEMP_PIN_CHANNEL AIO0_PIN + +// ANALOG_MASK is a bitmask of all analog channels used- if you use more than one analog input, bitwise-or them all together +#define ANALOG_MASK MASK(TEMP_PIN_CHANNEL) + +// how many temperature sensors do you have? +#define NUM_TEMP_SENSORS 1 + +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* If your temperature sensor has no associated heater, enter '255' as the * +* heater index. Unassociated temperature sensors are still read, but they * +* do not affect firmware operation * +* * +* for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * +* 255 * +* * +\***************************************************************************/ + +#ifdef TEMP_C +struct { + uint8_t temp_type; + uint8_t temp_pin; + + uint8_t heater_index; +} temp_sensors[NUM_TEMP_SENSORS] = +{ + { + TT_INTERCOM, + 0, + 0 + } +}; +#endif + + + +/***************************************************************************\ +* * +* 5. HEATERS * +* * +\***************************************************************************/ + +// number of heaters- for GEN3, set to zero as extruder manages the heater by itself +#define NUM_HEATERS 0 + +/***************************************************************************\ +* * +* Fill in the following struct according to your hardware * +* * +* If your heater isn't on a PWM-able pin, set heater_pwm to zero and we'll * +* use bang-bang output. Note that PID will still be used * +* * +* If a heater isn't attached to a temperature sensor above, it can still be * +* controlled by host but otherwise is ignored by firmware * +* * +\***************************************************************************/ + +#ifdef HEATER_C +struct { + volatile uint8_t *heater_port; + uint8_t heater_pin; + volatile uint8_t *heater_pwm; +} heaters[NUM_HEATERS]/* = +{ + { + &PORTD, + PIND6, + &OCR0A + } +}*/; +#endif + + + +/***************************************************************************\ +* * +* 6. COMMUNICATION OPTIONS * +* * +\***************************************************************************/ + +/* + RepRap Host changes it's communications protocol from time to time and intentionally avoids backwards compatibility. Set this to the date the source code of your Host was fetched from RepRap's repository, which is likely also the build date. + See the discussion on the reprap-dev mailing list from 11 Oct. 2010. + + Undefine it for best human readability, set it to an old date for compatibility with hosts before August 2010 +*/ +// #define REPRAP_HOST_COMPATIBILITY 19750101 +#define REPRAP_HOST_COMPATIBILITY 20100806 +// #define REPRAP_HOST_COMPATIBILITY + +/* + Xon/Xoff flow control. + Redundant when using RepRap Host for sending GCode, but mandatory when sending GCode files with a plain terminal emulator, like GtkTerm (Linux), CoolTerm (Mac) or HyperTerminal (Windows). + Can also be set in Makefile +*/ +// #define XONXOFF + + + +/***************************************************************************\ +* * +* 7. MISCELLANEOUS OPTIONS * +* * +\***************************************************************************/ + +/* + move buffer size, in number of moves + note that each move takes a fair chunk of ram (69 bytes as of this writing) so don't make the buffer too big - a bigger serial readbuffer may help more than increasing this unless your gcodes are more than 70 characters long on average. + however, a larger movebuffer will probably help with lots of short consecutive moves, as each move takes a bunch of math (hence time) to set up so a longer buffer allows more of the math to be done during preceding longer moves +*/ +#define MOVEBUFFER_SIZE 8 + +/* + FiveD on Arduino implements a watchdog, which has to be reset every 250ms or it will reboot the controller. As rebooting (and letting the GCode sending application trying to continue the build with a then different Home point) is probably even worse than just hanging, and there is no better restore code in place, this is disabled for now. +*/ +// #define USE_WATCHDOG + +/* + analog subsystem stuff + REFERENCE - which analog reference to use. see analog.h for choices +*/ +#define REFERENCE REFERENCE_AVCC + +/* + this option makes the step interrupt interruptible (nested). + this should help immensely with dropped serial characters, but may also make debugging infuriating due to the complexities arising from nested interrupts +*/ +#define STEP_INTERRUPT_INTERRUPTIBLE 1 + +/* + temperature history count. This is how many temperature readings to keep in order to calculate derivative in PID loop + higher values make PID derivative term more stable at the expense of reaction time +*/ +#define TH_COUNT 8 // this is the scaling of internally stored PID values. 1024L is a good value #define PID_SCALE 1024L + + +/***************************************************************************\ +* * +* 8. APPENDIX A - PWMABLE PINS AND MAPPINGS * +* * +* * +* list of PWM-able pins and corresponding timers * +* timer1 is used for step timing so don't use OC1A/OC1B * +* * +* For the atmega168/328, timer/pin mappings are as follows * +* * +* OCR0A - PD6 * +* OCR0B - PD5 * +* OCR2A - PB3 * +* OCR2B - PD3 * +* * +* For the atmega644, timer/pin mappings are as follows * +* * +* OCR0A - PB3 * +* OCR0B - PB4 * +* OCR2A - PD7 * +* OCR2B - PD6 * +* * +* For the atmega1280, timer/pin mappings are as follows * +* * +* OC0A - PB7 * +* OC0B - PG5 * +* OC2A - PB4 * +* OC2B - PH6 * +* OC3A - PE3 * +* OC3B - PE4 * +* OC3C - PE5 * +* OC4A - PH3 * +* OC4B - PH4 * +* OC4C - PH5 * +* OC5A - PL3 * +* OC5B - PL4 * +* OC5C - PL5 * +* * +\***************************************************************************/ + #endif /* _CONFIG_H */ From 952ad4e2f32b0477a1890a79d78c611da7589e7d Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:27:50 +1100 Subject: [PATCH 33/82] whitespace changes --- analog.c | 67 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/analog.c b/analog.c index f04af5c..346551b 100644 --- a/analog.c +++ b/analog.c @@ -4,6 +4,7 @@ #ifndef ANALOG_MASK #warning define ANALOG_MASK as a bitmask of all the analog channels you wish to use + #warning defining ANALOG_MASK as zero will prevent the analog subsystem from starting #error ANALOG_MASK not defined #endif @@ -40,26 +41,26 @@ volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss"))); void analog_init() { #if ANALOG_MASK > 0 - #ifdef PRR - PRR &= ~MASK(PRADC); - #elif defined PRR0 - PRR0 &= ~MASK(PRADC); - #endif - - ADMUX = REFERENCE; - - // ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz. - ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0); + #ifdef PRR + PRR &= ~MASK(PRADC); + #elif defined PRR0 + PRR0 &= ~MASK(PRADC); + #endif - adc_counter = 0; - adc_running_mask = 1; + ADMUX = REFERENCE; - DDRC &= ANALOG_MASK; - DIDR0 = ANALOG_MASK & 0x3F; + // ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz. + ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0); - // now we start the first conversion and leave the rest to the interrupt - ADCSRA |= MASK(ADIE) | MASK(ADSC); - #endif + adc_counter = 0; + adc_running_mask = 1; + + DDRC &= ANALOG_MASK; + DIDR0 = ANALOG_MASK & 0x3F; + + // now we start the first conversion and leave the rest to the interrupt + ADCSRA |= MASK(ADIE) | MASK(ADSC); + #endif /* ANALOG_MASK > 0 */ } ISR(ADC_vect, ISR_NOBLOCK) { @@ -81,19 +82,23 @@ ISR(ADC_vect, ISR_NOBLOCK) { } uint16_t analog_read(uint8_t channel) { - uint16_t r; + #if ANALOG_MASK > 0 + uint16_t r; - uint8_t sreg; - // save interrupt flag - sreg = SREG; - // disable interrupts - cli(); - - // atomic 16-bit copy - r = adc_result[channel]; - - // restore interrupt flag - SREG = sreg; - - return r; + uint8_t sreg; + // save interrupt flag + sreg = SREG; + // disable interrupts + cli(); + + // atomic 16-bit copy + r = adc_result[channel]; + + // restore interrupt flag + SREG = sreg; + + return r; + #else + return 0; + #endif } From 5ae5a0348de8525b719d9e0a32683c92ecf9d26f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:28:28 +1100 Subject: [PATCH 34/82] add -mcall-prologues to optimisations for a smaller binary --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7bea58d..cae251b 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ OBJCOPY = $(ARCH)objcopy DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3 # DEFS += "-DDEBUG=1" -OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once +OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -mcall-prologues # OPTIMIZE = -O0 CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps LDFLAGS = -Wl,--as-needed -Wl,--gc-sections From 9a31d969a552ccaa52876ede642a383e5e792c4b Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:33:01 +1100 Subject: [PATCH 35/82] get capabilities from config --- gcode_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcode_process.c b/gcode_process.c index a28918e..e701856 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -264,7 +264,7 @@ void process_gcode_command() { break; // M115- capabilities string case 115: - serial_writestr_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 HEATER_COUNT:1\n")); + sersendf_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d\n"), 1, NUM_TEMP_SENSORS, NUM_HEATERS); break; #if NUM_HEATERS > 0 From 41f68be450e7de019e6fa48c8ee1dcb83f6130d4 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:33:42 +1100 Subject: [PATCH 36/82] default to atmega644p for GEN3 out-of-box compatibility --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cae251b..f91d805 100644 --- a/Makefile +++ b/Makefile @@ -40,8 +40,8 @@ SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp ############################################################################## #MCU_TARGET = atmega168 -MCU_TARGET = atmega328p -#MCU_TARGET = atmega644p +# MCU_TARGET = atmega328p +MCU_TARGET = atmega644p #MCU_TARGET = atmega1280 F_CPU = 16000000L From a4b0c2f848b7622fa641a01b43af784cb1b8b499 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 18:39:15 +1100 Subject: [PATCH 37/82] rearrange Makefile, hopefully easier to access tunables for first-timers --- Makefile | 61 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index f91d805..054e3ae 100644 --- a/Makefile +++ b/Makefile @@ -23,39 +23,19 @@ # # ############################################################################## -############################################################################## -# # -# Change these to suit your application # -# # -############################################################################## - -PROGRAM = mendel - -SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c pinio.c - ############################################################################## # # # Change these to suit your hardware # # # ############################################################################## -#MCU_TARGET = atmega168 +# MCU_TARGET = atmega168 # MCU_TARGET = atmega328p MCU_TARGET = atmega644p -#MCU_TARGET = atmega1280 +# MCU_TARGET = atmega1280 + F_CPU = 16000000L -############################################################################## -# # -# These defaults should be ok, change if you need to # -# # -############################################################################## - -ARCH = avr- -CC = $(ARCH)gcc -OBJDUMP = $(ARCH)objdump -OBJCOPY = $(ARCH)objcopy - ############################################################################## # # # Available Defines: # @@ -70,16 +50,20 @@ OBJCOPY = $(ARCH)objcopy # enables start/stop ramping # # GEN3 # # build for standard reprap electronics instead of your custom rig # +# HOST # +# this is the motherboard for GEN3- don't touch! Extruder has its own # +# Makefile. # # # ############################################################################## DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3 # DEFS += "-DDEBUG=1" -OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -mcall-prologues -# OPTIMIZE = -O0 -CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps -LDFLAGS = -Wl,--as-needed -Wl,--gc-sections +############################################################################## +# # +# Programmer settings for "make program" # +# # +############################################################################## AVRDUDE = avrdude AVRDUDECONF = /etc/avrdude.conf @@ -92,12 +76,35 @@ AVRDUDECONF = /etc/avrdude.conf # MODE="0660" # # # ############################################################################## + PROGPORT = /dev/arduino + # atmega168 #PROGBAUD = 19200 # atmega328p, 644p, 1280 PROGBAUD = 57600 + +############################################################################## +# # +# These defaults should be ok, change if you need to # +# # +############################################################################## + +PROGRAM = mendel + +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c pinio.c + +ARCH = avr- +CC = $(ARCH)gcc +OBJDUMP = $(ARCH)objdump +OBJCOPY = $(ARCH)objcopy + +OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -mcall-prologues +# OPTIMIZE = -O0 +CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps +LDFLAGS = -Wl,--as-needed -Wl,--gc-sections + OBJ = $(patsubst %.c,%.o,${SOURCES}) .PHONY: all program clean size From d2df1121798fece4a471a7c7b1f502778a83613b Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 20:56:33 +1100 Subject: [PATCH 38/82] force compare doesn't fire an interrupt, work around --- timer.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/timer.c b/timer.c index ddd5e60..2390ff0 100644 --- a/timer.c +++ b/timer.c @@ -21,11 +21,9 @@ ISR(TIMER1_CAPT_vect) { */ if (next_step_time > TICK_TIME) next_step_time -= TICK_TIME; - else { - if (next_step_time > 0) { - OCR1A = next_step_time & 0xFFFF; - TIMSK1 |= MASK(OCIE1A); - } + else if (next_step_time > 0) { + OCR1A = next_step_time & 0xFFFF; + TIMSK1 |= MASK(OCIE1A); } /* @@ -50,7 +48,8 @@ ISR(TIMER1_CAPT_vect) { } } -ISR(TIMER1_COMPA_vect) { +void timer1_compa_isr(void) __attribute__ ((hot)); +void timer1_compa_isr() { // led on WRITE(SCK, 1); @@ -60,15 +59,17 @@ ISR(TIMER1_COMPA_vect) { // ensure we don't interrupt again unless timer is reset next_step_time = 0; - /* - stepper tick - */ + // stepper tick queue_step(); // led off WRITE(SCK, 0); } +ISR(TIMER1_COMPA_vect) { + timer1_compa_isr(); +} + void timer_init() { // no outputs @@ -95,11 +96,11 @@ void setTimer(uint32_t delay) // mangle timer variables next_step_time = delay + TCNT1; if (delay <= 16) { - // force interrupt - // TODO: datasheet says force only doesn't work in CTC:COMPA mode, test if CTC:ICR mode allows force - TIMSK1 |= MASK(OCIE1A); - TCCR1C |= MASK(FOC1A); + // unfortunately, force registers don't trigger an interrupt, so we do the following + // don't step from timer interrupt next_step_time = 0; + // "fire" ISR- maybe it sets a new timeout + timer1_compa_isr(); } else if (delay <= TICK_TIME) { OCR1A = next_step_time & 0xFFFF; From 8586e3ebbc53f1ecf67fc8064b22fa2353953cf3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 20:57:20 +1100 Subject: [PATCH 39/82] force recompile if Makefile changes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 054e3ae..ffac8f0 100644 --- a/Makefile +++ b/Makefile @@ -132,7 +132,7 @@ config.h: config.h.dist @echo "Please review config.h, as config.h.dist is more recent." @false -%.o: %.c config.h +%.o: %.c config.h Makefile @echo " CC $@" @$(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $(subst .o,.c,$@) From 15349a1760d75b3c20866101087f90173af140b0 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 21:12:30 +1100 Subject: [PATCH 40/82] use labs() instead of ABS --- dda.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/dda.c b/dda.c index afa7312..554f16e 100644 --- a/dda.c +++ b/dda.c @@ -76,14 +76,6 @@ #define UM_PER_STEP_Z 1000L / ((uint32_t) STEPS_PER_MM_Z) #define UM_PER_STEP_E 1000L / ((uint32_t) STEPS_PER_MM_E) -/* - Maths -*/ - -#ifndef ABS -#define ABS(v) (((v) >= 0)?(v):(-(v))) -#endif - /* step timeout */ @@ -187,10 +179,10 @@ void dda_create(DDA *dda, TARGET *target) { // we end at the passed target memcpy(&(dda->endpoint), target, sizeof(TARGET)); - dda->x_delta = ABS(target->X - startpoint.X); - dda->y_delta = ABS(target->Y - startpoint.Y); - dda->z_delta = ABS(target->Z - startpoint.Z); - dda->e_delta = ABS(target->E - startpoint.E); + dda->x_delta = labs(target->X - startpoint.X); + dda->y_delta = labs(target->Y - startpoint.Y); + dda->z_delta = labs(target->Z - startpoint.Z); + dda->e_delta = labs(target->E - startpoint.E); dda->x_direction = (target->X >= startpoint.X)?1:0; dda->y_direction = (target->Y >= startpoint.Y)?1:0; From ba7d9a082ff8dc373580dfe42a1d10e7b6eb96ff Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 21:40:10 +1100 Subject: [PATCH 41/82] more use of sersendf_P, comments for clarity, enable steppers --- dda.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/dda.c b/dda.c index 554f16e..ad96dac 100644 --- a/dda.c +++ b/dda.c @@ -214,9 +214,8 @@ void dda_create(DDA *dda, TARGET *target) { if (dda->e_delta > dda->total_steps) dda->total_steps = dda->e_delta; - if (debug_flags & DEBUG_DDA) { - serial_writestr_P(PSTR("ts:")); serwrite_uint32(dda->total_steps); - } + if (debug_flags & DEBUG_DDA) + sersendf_P(PSTR("ts:%lu"), dda->total_steps); if (dda->total_steps == 0) { dda->nullmove = 1; @@ -244,9 +243,8 @@ void dda_create(DDA *dda, TARGET *target) { if (distance < 2) distance = dda->e_delta * UM_PER_STEP_E; - if (debug_flags & DEBUG_DDA) { - serial_writestr_P(PSTR(",ds:")); serwrite_uint32(distance); - } + if (debug_flags & DEBUG_DDA) + sersendf_P(PSTR(",ds:%lu"), distance); // pre-calculate move speed in millimeter microseconds per step minute for less math in interrupt context // mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min @@ -268,15 +266,19 @@ void dda_create(DDA *dda, TARGET *target) { // similarly, find out how fast we can run our axes. // do this for each axis individually, as the combined speed of two or more axes can be higher than the capabilities of a single one. c_limit = 0; + // check X axis c_limit_calc = ( (dda->x_delta * (UM_PER_STEP_X * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; + // check Y axis c_limit_calc = ( (dda->y_delta * (UM_PER_STEP_Y * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Y) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; + // check Z axis c_limit_calc = ( (dda->z_delta * (UM_PER_STEP_Z * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Z) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; + // check E axis c_limit_calc = ( (dda->e_delta * (UM_PER_STEP_E * 2400L)) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_E) << 8; if (c_limit_calc > c_limit) c_limit = c_limit_calc; @@ -290,10 +292,8 @@ void dda_create(DDA *dda, TARGET *target) { if (dda->end_c < c_limit) dda->end_c = c_limit; - if (debug_flags & DEBUG_DDA) { - serial_writestr_P(PSTR(",md:")); serwrite_uint32(move_duration); - serial_writestr_P(PSTR(",c:")); serwrite_uint32(dda->c >> 8); - } + if (debug_flags & DEBUG_DDA) + sersendf_P(PSTR(",md:%lu,c:%lu"), move_duration, dda->c >> 8); if (dda->c != dda->end_c) { uint32_t stF = startpoint.F / 4; @@ -329,9 +329,8 @@ void dda_create(DDA *dda, TARGET *target) { dda->n = (((int32_t) ssq / dsq) * (int32_t) dda->total_steps) + 1; } - if (debug_flags & DEBUG_DDA) { + if (debug_flags & DEBUG_DDA) sersendf_P(PSTR("\n{DDA:CA end_c:%lu, n:%ld, md:%lu, ssq:%lu, esq:%lu, dsq:%lu, msbssq:%u, msbtot:%u}\n"), dda->end_c >> 8, dda->n, move_duration, ssq, esq, dsq, msb_ssq, msb_tot); - } dda->accel = 1; } @@ -377,13 +376,19 @@ void dda_start(DDA *dda) { } else { if (dda->waitfor_temp) { - serial_writestr_P(PSTR("Waiting for target temp\n")); + #ifndef REPRAP_HOST_COMPATIBILITY + serial_writestr_P(PSTR("Waiting for target temp\n")); + #endif } else { // ensure steppers are ready to go steptimeout = 0; power_on(); - + x_enable(); + y_enable(); + if (dda->z_delta) + z_enable(); + // set direction outputs x_direction(dda->x_direction); y_direction(dda->y_direction); From 98882e1c69a142cd2e0bc3964a71456758c654f8 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 8 Nov 2010 22:13:50 +1100 Subject: [PATCH 42/82] add temporal step algorithm for testing --- Makefile | 3 + config.h.dist | 16 +++- dda.c | 239 ++++++++++++++++++++++++++++++++++---------------- dda.h | 6 ++ 4 files changed, 189 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index ffac8f0..afede04 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,9 @@ F_CPU = 16000000L # enables reprap-style acceleration # # ACCELERATION_RAMPING # # enables start/stop ramping # +# ACCELERATION_TEMPORAL # +# enables experimental temporal step algorithm - not technically a type of # +# acceleration, but since it controls step timing it seems appropriate # # GEN3 # # build for standard reprap electronics instead of your custom rig # # HOST # diff --git a/config.h.dist b/config.h.dist index fb11c23..2f6c9b9 100644 --- a/config.h.dist +++ b/config.h.dist @@ -77,7 +77,21 @@ Each movement starts at (almost) no speed, linearly accelerates to target speed and decelerates just in time to smoothly stop at the target. alternative to ACCELERATION_REPRAP Can also be set in Makefile */ -#define ACCELERATION_RAMPING +// #define ACCELERATION_RAMPING + +/* + temporal step algorithm + This algorithm causes the timer to fire when any axis needs to step, instead of synchronising to the axis with the most steps. + + This algorithm is not a type of acceleration, and I haven't worked out how to integrate acceleration with it. + However it does control step timing, so acceleration algorithms seemed appropriate + + The Bresenham algorithm is great for drawing lines, but not so good for steppers - In the case where X steps 3 times to Y's two, Y experiences massive jitter as it steps in sync with X every 2 out of 3 X steps. This is a worst-case, but the problem exists for most non-45/90 degree moves. At higher speeds, the jitter /will/ cause position loss and unnecessary vibration. + This algorithm instead calculates when a step occurs on any axis, and sets the timer to that value. + + // TODO: figure out how to add acceleration to this algorithm +*/ +// #define ACCELERATION_TEMPORAL // how fast to accelerate when using ACCELERATION_RAMPING // smaller values give quicker acceleration diff --git a/dda.c b/dda.c index ad96dac..2baa768 100644 --- a/dda.c +++ b/dda.c @@ -1,6 +1,7 @@ #include "dda.h" #include +#include #include #include "timer.h" @@ -10,6 +11,7 @@ #include "debug.h" #include "sersendf.h" #include "pinio.h" +#include "config.h" /* X Stepper @@ -189,22 +191,8 @@ void dda_create(DDA *dda, TARGET *target) { dda->z_direction = (target->Z >= startpoint.Z)?1:0; dda->e_direction = (target->E >= startpoint.E)?1:0; - if (debug_flags & DEBUG_DDA) { - if (dda->x_direction == 0) - serial_writechar('-'); - serwrite_uint32(dda->x_delta); serial_writechar(','); - if (dda->y_direction == 0) - serial_writechar('-'); - serwrite_uint32(dda->y_delta); serial_writechar(','); - if (dda->z_direction == 0) - serial_writechar('-'); - serwrite_uint32(dda->z_delta); serial_writechar(','); - if (dda->e_direction == 0) - serial_writechar('-'); - serwrite_uint32(dda->e_delta); - - serial_writestr_P(PSTR("] [")); - } + if (debug_flags & DEBUG_DDA) + sersendf_P(PSTR("%ld,%ld,%ld,%ld] ["), target->X - startpoint.X, target->Y - startpoint.Y, target->Z - startpoint.Z, target->E - startpoint.E); dda->total_steps = dda->x_delta; if (dda->y_delta > dda->total_steps) @@ -229,9 +217,6 @@ void dda_create(DDA *dda, TARGET *target) { if (dda->z_delta) z_enable(); - dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter = - -(dda->total_steps >> 1); - // since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation. if (dda->z_delta == 0) distance = approx_distance(dda->x_delta * UM_PER_STEP_X, dda->y_delta * UM_PER_STEP_Y); @@ -239,30 +224,38 @@ void dda_create(DDA *dda, TARGET *target) { distance = dda->z_delta * UM_PER_STEP_Z; else distance = approx_distance_3(dda->x_delta * UM_PER_STEP_X, dda->y_delta * UM_PER_STEP_Y, dda->z_delta * UM_PER_STEP_Z); - + if (distance < 2) distance = dda->e_delta * UM_PER_STEP_E; - + if (debug_flags & DEBUG_DDA) sersendf_P(PSTR(",ds:%lu"), distance); + + #ifdef ACCELERATION_TEMPORAL + // bracket part of this equation in an attempt to avoid overflow: 60 * 16MHz * 5mm is >32 bits + uint32_t move_duration = distance * (60 * F_CPU / startpoint.F); + #else + dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter = + -(dda->total_steps >> 1); - // pre-calculate move speed in millimeter microseconds per step minute for less math in interrupt context - // mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min - // note: um (distance) * 60000 == mm * 60000000 - // so in the interrupt we must simply calculate - // mm.us per step.min / mm per min (F) = us per step + // pre-calculate move speed in millimeter microseconds per step minute for less math in interrupt context + // mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min + // note: um (distance) * 60000 == mm * 60000000 + // so in the interrupt we must simply calculate + // mm.us per step.min / mm per min (F) = us per step - // break this calculation up a bit and lose some precision because 300,000um * 60000 is too big for a uint32 - // calculate this with a uint64 if you need the precision, but it'll take longer so routines with lots of short moves may suffer - // 2^32/6000 is about 715mm which should be plenty + // break this calculation up a bit and lose some precision because 300,000um * 60000 is too big for a uint32 + // calculate this with a uint64 if you need the precision, but it'll take longer so routines with lots of short moves may suffer + // 2^32/6000 is about 715mm which should be plenty - // changed * 10 to * (F_CPU / 100000) so we can work in cpu_ticks rather than microseconds. - // timer.c setTimer() routine altered for same reason - - // changed distance * 6000 .. * F_CPU / 100000 to - // distance * 2400 .. * F_CPU / 40000 so we can move a distance of up to 1800mm without overflowing - uint32_t move_duration = ((distance * 2400) / dda->total_steps) * (F_CPU / 40000); + // changed * 10 to * (F_CPU / 100000) so we can work in cpu_ticks rather than microseconds. + // timer.c setTimer() routine altered for same reason + // changed distance * 6000 .. * F_CPU / 100000 to + // distance * 2400 .. * F_CPU / 40000 so we can move a distance of up to 1800mm without overflowing + uint32_t move_duration = ((distance * 2400) / dda->total_steps) * (F_CPU / 40000); + #endif + // similarly, find out how fast we can run our axes. // do this for each axis individually, as the combined speed of two or more axes can be higher than the capabilities of a single one. c_limit = 0; @@ -337,7 +330,7 @@ void dda_create(DDA *dda, TARGET *target) { else dda->accel = 0; #elif defined ACCELERATION_RAMPING - // add the last bit of dda->total_steps to always round up + // add the last bit of dda->total_steps to always round up dda->ramp_steps = dda->total_steps / 2 + (dda->total_steps & 1); dda->step_no = 0; // c is initial step time in IOclk ticks @@ -347,6 +340,26 @@ void dda_create(DDA *dda, TARGET *target) { dda->c_min = c_limit; dda->n = 1; dda->ramp_state = RAMP_UP; + #elif defined ACCELERATION_TEMPORAL + dda->x_step_interval = move_duration / dda->x_delta; + dda->y_step_interval = move_duration / dda->y_delta; + dda->z_step_interval = move_duration / dda->z_delta; + dda->e_step_interval = move_duration / dda->e_delta; + + dda->x_counter = 0; + dda->y_counter = 0; + dda->z_counter = 0; + dda->e_counter = 0; + + dda->c = dda->x_step_interval; + if (dda->y_step_interval < dda->c) + dda->c = dda->y_step_interval; + if (dda->z_step_interval < dda->c) + dda->c = dda->z_step_interval; + if (dda->e_step_interval < dda->c) + dda->c = dda->e_step_interval; + + dda->c <<= 8; #else dda->c = (move_duration / target->F) << 8; if (dda->c < c_limit) @@ -412,64 +425,115 @@ void dda_step(DDA *dda) { // called from interrupt context! keep it as simple as possible uint8_t did_step = 0; - if ((current_position.X != dda->endpoint.X) /* && - (x_max() != dda->x_direction) && (x_min() == dda->x_direction) */) { - dda->x_counter -= dda->x_delta; - if (dda->x_counter < 0) { - x_step(); - did_step = 1; + #ifdef ACCELERATION_TEMPORAL + if (dda->x_counter > dda->x_step_interval) { + if ((current_position.X != dda->endpoint.X) /* && + (x_max() != dda->x_direction) && (x_min() == dda->x_direction) */) { + x_step(); if (dda->x_direction) current_position.X++; else current_position.X--; - - dda->x_counter += dda->total_steps; + } + dda->x_counter -= dda->x_step_interval; + dda->x_delta--; } - } - - if ((current_position.Y != dda->endpoint.Y) /* && - (y_max() != dda->y_direction) && (y_min() == dda->y_direction) */) { - dda->y_counter -= dda->y_delta; - if (dda->y_counter < 0) { - y_step(); - did_step = 1; + if (dda->y_counter > dda->y_step_interval) { + if ((current_position.Y != dda->endpoint.Y) /* && + (y_max() != dda->y_direction) && (y_min() == dda->y_direction) */) { + y_step(); if (dda->y_direction) current_position.Y++; else current_position.Y--; - - dda->y_counter += dda->total_steps; + } + dda->y_counter -= dda->y_step_interval; + dda->y_delta--; } - } - - if ((current_position.Z != dda->endpoint.Z) /* && - (z_max() != dda->z_direction) && (z_min() == dda->z_direction) */) { - dda->z_counter -= dda->z_delta; - if (dda->z_counter < 0) { - z_step(); - did_step = 1; + if (dda->z_counter > dda->z_step_interval) { + if ((current_position.Z != dda->endpoint.Z) /* && + (z_max() != dda->z_direction) && (z_min() == dda->z_direction) */) { + z_step(); if (dda->z_direction) current_position.Z++; else current_position.Z--; - - dda->z_counter += dda->total_steps; + } + dda->z_counter -= dda->z_step_interval; + dda->z_delta--; } - } - - if (current_position.E != dda->endpoint.E) { - dda->e_counter -= dda->e_delta; - if (dda->e_counter < 0) { - e_step(); - did_step = 1; + if (dda->e_counter > dda->e_step_interval) { + if ((current_position.E != dda->endpoint.E) /* && + (e_max() != dda->e_direction) && (e_min() == dda->e_direction) */) { + e_step(); if (dda->e_direction) current_position.E++; else current_position.E--; - - dda->e_counter += dda->total_steps; + } + dda->e_counter -= dda->e_step_interval; + dda->e_delta--; } - } + #else + if ((current_position.X != dda->endpoint.X) /* && + (x_max() != dda->x_direction) && (x_min() == dda->x_direction) */) { + dda->x_counter -= dda->x_delta; + if (dda->x_counter < 0) { + x_step(); + did_step = 1; + if (dda->x_direction) + current_position.X++; + else + current_position.X--; + + dda->x_counter += dda->total_steps; + } + } + + if ((current_position.Y != dda->endpoint.Y) /* && + (y_max() != dda->y_direction) && (y_min() == dda->y_direction) */) { + dda->y_counter -= dda->y_delta; + if (dda->y_counter < 0) { + y_step(); + did_step = 1; + if (dda->y_direction) + current_position.Y++; + else + current_position.Y--; + + dda->y_counter += dda->total_steps; + } + } + + if ((current_position.Z != dda->endpoint.Z) /* && + (z_max() != dda->z_direction) && (z_min() == dda->z_direction) */) { + dda->z_counter -= dda->z_delta; + if (dda->z_counter < 0) { + z_step(); + did_step = 1; + if (dda->z_direction) + current_position.Z++; + else + current_position.Z--; + + dda->z_counter += dda->total_steps; + } + } + + if (current_position.E != dda->endpoint.E) { + dda->e_counter -= dda->e_delta; + if (dda->e_counter < 0) { + e_step(); + did_step = 1; + if (dda->e_direction) + current_position.E++; + else + current_position.E--; + + dda->e_counter += dda->total_steps; + } + } + #endif #if STEP_INTERRUPT_INTERRUPTIBLE // since we have sent steps to all the motors that will be stepping and the rest of this function isn't so time critical, @@ -524,6 +588,32 @@ void dda_step(DDA *dda) { } dda->step_no++; #endif + #ifdef ACCELERATION_TEMPORAL + dda->c = dda->x_step_interval - dda->x_counter; + if ((dda->y_step_interval - dda->y_counter) < dda->c) + dda->c = dda->y_step_interval - dda->y_counter; + if ((dda->z_step_interval - dda->z_counter) < dda->c) + dda->c = dda->z_step_interval - dda->z_counter; + if ((dda->e_step_interval - dda->e_counter) < dda->c) + dda->c = dda->e_step_interval - dda->e_counter; + + if (dda->x_delta) + dda->x_counter += dda->c; + if (dda->y_delta) + dda->y_counter += dda->c; + if (dda->z_delta) + dda->z_counter += dda->c; + if (dda->e_delta) + dda->e_counter += dda->c; + if ( + (dda->x_delta > 0) || + (dda->y_delta > 0) || + (dda->z_delta > 0) || + (dda->e_delta > 0)) + did_step = 1; + + dda->c <<= 8; + #endif if (did_step) { // we stepped, reset timeout @@ -540,6 +630,7 @@ void dda_step(DDA *dda) { // in theory, we *could* update F every step, but that would require a divide in interrupt context which should be avoided if at all possible current_position.F = dda->endpoint.F; } + setTimer(dda->c >> 8); // turn off step outputs, hopefully they've been on long enough by now to register with the drivers diff --git a/dda.h b/dda.h index a7f374b..48f6808 100644 --- a/dda.h +++ b/dda.h @@ -86,6 +86,12 @@ typedef struct { int32_t n; ramp_state_t ramp_state; #endif + #ifdef ACCELERATION_TEMPORAL + uint32_t x_step_interval; + uint32_t y_step_interval; + uint32_t z_step_interval; + uint32_t e_step_interval; + #endif } DDA; /* From 37f6dbff233ad6772b0181fd1e4d898fd4d52089 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 9 Nov 2010 10:59:13 +1100 Subject: [PATCH 43/82] preliminary DC motor extruder support --- config.h.dist | 9 ++++++++- dda.c | 22 +++++++++++++++++++--- heater.c | 9 +-------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/config.h.dist b/config.h.dist index 2f6c9b9..a1ea657 100644 --- a/config.h.dist +++ b/config.h.dist @@ -100,7 +100,7 @@ #ifdef ACCELERATION_REPRAP #ifdef ACCELERATION_RAMPING - #error Can't use ACCELERATION_REPRAP and ACCELERATION_RAMPING together. + #error "Can't use ACCELERATION_REPRAP and ACCELERATION_RAMPING together." #endif #endif @@ -310,6 +310,13 @@ struct { */ #define MOVEBUFFER_SIZE 8 +/* + DC extruder + If you have a DC motor extruder, configure it as a "heater" above and define this value as the index. +*/ +// #define DC_EXTRUDER 1 +// #define DC_EXTRUDER_PWM 180 + /* FiveD on Arduino implements a watchdog, which has to be reset every 250ms or it will reboot the controller. As rebooting (and letting the GCode sending application trying to continue the build with a then different Home point) is probably even worse than just hanging, and there is no better restore code in place, this is disabled for now. */ diff --git a/dda.c b/dda.c index 2baa768..87d6183 100644 --- a/dda.c +++ b/dda.c @@ -13,6 +13,10 @@ #include "pinio.h" #include "config.h" +#ifdef DC_EXTRUDER + #include "heater.h" +#endif + /* X Stepper */ @@ -68,8 +72,11 @@ (so we don't have to delay in interrupt context) */ -#define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) - +#ifndef DC_EXTRUDER + #define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) +#else + #define unstep() do { _x_step(0); _y_step(0); _z_step(0); } while (0) +#endif /* Used in distance calculation during DDA setup */ @@ -401,12 +408,18 @@ void dda_start(DDA *dda) { y_enable(); if (dda->z_delta) z_enable(); - + // set direction outputs x_direction(dda->x_direction); y_direction(dda->y_direction); z_direction(dda->z_direction); e_direction(dda->e_direction); + + #ifdef DC_EXTRUDER + if (dda->e_delta) + heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM); + #endif + } // ensure this dda starts @@ -629,6 +642,9 @@ void dda_step(DDA *dda) { // linear acceleration code doesn't alter F during a move, so we must update it here // in theory, we *could* update F every step, but that would require a divide in interrupt context which should be avoided if at all possible current_position.F = dda->endpoint.F; + #ifdef DC_EXTRUDER + heater_set(DC_EXTRUDER, 0); + #endif } setTimer(dda->c >> 8); diff --git a/heater.c b/heater.c index a5b2dd6..525a58e 100644 --- a/heater.c +++ b/heater.c @@ -46,14 +46,7 @@ typedef struct { int16_t EE_i_limit; } EE_factor; -EE_factor EEMEM EE_factors[NUM_HEATERS] = { - { - DEFAULT_P, - DEFAULT_I, - DEFAULT_D, - DEFAULT_I_LIMIT - } -}; +EE_factor EEMEM EE_factors[NUM_HEATERS]; void heater_init() { #if NUM_HEATERS > 0 From 5460750ee39fa594438aefc5700dd1a9e809205c Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 10 Nov 2010 15:33:57 +1100 Subject: [PATCH 44/82] update README to match new file layout --- README | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README b/README index 5056a03..ee5de4d 100644 --- a/README +++ b/README @@ -108,11 +108,11 @@ The PID code in heater.c is probably quite generalisable, and seems to work well *** analog.[ch] This is the analog subsystem. Only used if you have a thermistor or ad595 -*** arduino.h -Pin mappings and helper functions for various arduinos ('168/'328-based and '644-based only so far, feel free to add '1280 and post a patch) +*** arduino.h, arduino_[chip].h +Pin mappings and helper functions for various atmegas -*** clock.[ch] -A system clock for periodic tasks. Supports a long-running clock, but this is disabled by default as nothing uses it (yet!) +*** config.h.dist, config.h +Configuration for your electronics and hardware. Copy config.h.dist to config.h, edit config.h to suit *** copier.[ch] A totally untested and currently unused chunk of code for copying firmware to another identical chip @@ -126,20 +126,29 @@ The queue of moves received from the host. *** debug.[ch] Debugging aids +*** delay.[ch] +Delay functions + *** FiveD_on_Arduino.pde Allows firmware to be built in arduino ide *** func.sh Lots of host-side shell scripts for talking to firmware -*** gcode.[ch] -Gcode interpreter. Scaling of factors to internally used integer or fixed point happens here too. +*** gcode_parse.[ch] +Gcode parser. Scaling of factors to internally used integer or fixed point happens here too. + +*** gcode_process.[ch] +Gcodes actually get executed here after being parsed. *** heater.[ch] Heater management, including PID and PWM algorithms, and some configuration parameters -*** machine.h -Configuration variables to match firmware to your hardware +*** intercom.[ch] +Gen3 serial link control and communication + +*** LICENSE +Gnu GPL2 license *** Makefile instructions for make on how to build firmware. has a list of modules to build which may need to be updated every so often @@ -147,8 +156,8 @@ instructions for make on how to build firmware. has a list of modules to build w *** mendel.c Firmware startup and main loop code -*** pinout.h -This file associates various functions with particular pins on your avr +*** pinio.h +A few I/O primitives *** README this file From 983308a892dc69e4716f25b6720c20f953a54495 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 10 Nov 2010 23:25:18 +1100 Subject: [PATCH 45/82] specify units for feedrate limits --- config.h.dist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.h.dist b/config.h.dist index a1ea657..a257d21 100644 --- a/config.h.dist +++ b/config.h.dist @@ -40,6 +40,8 @@ /* Values depending on the capabilities of your stepper motors and other mechanics. All numbers are integers, no decimals allowed. + + Units are mm/min */ // used for G0 rapid moves and as a cap for all other feedrates From 4298f7553f24a18b9142a87be3a45a2174be2908 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 00:49:12 +1100 Subject: [PATCH 46/82] always have TT_INTERCOM in list of sensor types --- temp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/temp.c b/temp.c index 9eec470..8023b8f 100644 --- a/temp.c +++ b/temp.c @@ -18,10 +18,8 @@ typedef enum { TT_THERMISTOR, TT_MAX6675, - TT_AD595 -#ifdef GEN3 - , TT_INTERCOM -#endif + TT_AD595, + TT_INTERCOM } temp_types; typedef enum { From 2b1fbe38db5fec94242d700e8ea412f2a41ae668 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 00:51:25 +1100 Subject: [PATCH 47/82] preliminary heater sanity check code, disabled by default until tested --- config.h.dist | 11 +++-- heater.c | 110 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/config.h.dist b/config.h.dist index a257d21..ffaf896 100644 --- a/config.h.dist +++ b/config.h.dist @@ -182,19 +182,21 @@ \***************************************************************************/ /* - TEMP_HYSTERESIS: actual temperature must be target +/- hysteresis before target temperature can be achieved + TEMP_HYSTERESIS: actual temperature must be target +/- hysteresis before target temperature can be achieved. + NOTE: format is 30.2 fixed point, so value of 20 actually means +/- 5 degrees + TEMP_RESIDENCY_TIME: actual temperature must be close to target for this long before target is achieved temperature is "achieved" for purposes of M109 and friends when actual temperature is within [hysteresis] of target for [residency] seconds */ -#define TEMP_HYSTERESIS 5 +#define TEMP_HYSTERESIS 20 #define TEMP_RESIDENCY_TIME 60 // which temperature sensors are you using? (intercom is the gen3-style separate extruder board) // #define TEMP_MAX6675 // #define TEMP_THERMISTOR // #define TEMP_AD595 -// #define TEMP_INTERCOM +#define TEMP_INTERCOM // if you selected thermistor or AD595, what pin is it on? (this value only used to fill ANALOG_MASK for you) #define TEMP_PIN_CHANNEL AIO0_PIN @@ -245,6 +247,9 @@ struct { // number of heaters- for GEN3, set to zero as extruder manages the heater by itself #define NUM_HEATERS 0 +// check if heater responds to changes in target temperature, disable and spit errors if not +// #define HEATER_SANITY_CHECK + /***************************************************************************\ * * * Fill in the following struct according to your hardware * diff --git a/heater.c b/heater.c index 525a58e..e71ca9b 100644 --- a/heater.c +++ b/heater.c @@ -1,14 +1,12 @@ #include "heater.h" +#include #include #include #include "arduino.h" -// #include "timer.h" #include "debug.h" -#ifdef DEBUG - #include "sersendf.h" -#endif +#include "sersendf.h" #define HEATER_C #include "config.h" @@ -21,21 +19,22 @@ struct { int16_t i_limit; } heaters_pid[NUM_HEATERS]; -// this struct holds the runtime heater data- PID counters and such +// this struct holds the runtime heater data- PID integrator history, temperature history, sanity checker struct { - int16_t heater_p; int16_t heater_i; - int16_t heater_d; - - uint8_t pid_output; - + uint16_t temp_history[TH_COUNT]; uint8_t temp_history_pointer; + + #ifdef HEATER_SANITY_CHECK + uint16_t sanity_counter; + uint16_t sane_temperature; + #endif } heaters_runtime[NUM_HEATERS]; #define DEFAULT_P 8192 #define DEFAULT_I 512 -#define DEFAULT_D -24576 +#define DEFAULT_D 24576 #define DEFAULT_I_LIMIT 384 // this lives in the eeprom so we can save our PID settings for each heater @@ -55,9 +54,10 @@ void heater_init() { for (i = 0; i < NUM_HEATERS; i++) { *(heaters[i].heater_port) &= ~MASK(heaters[i].heater_pin); // DDR is always 1 address below PORT. ugly code but saves ram and an extra field in heaters[] which will never be used anywhere but here - *((volatile uint8_t *) (heaters[i].heater_port - 1)) |= MASK(heaters[i].heater_pin); + *(heaters[i].heater_port - 1) |= MASK(heaters[i].heater_pin); if (heaters[i].heater_pwm) { *heaters[i].heater_pwm = 0; + // this is somewhat ugly too, but switch() won't accept pointers for reasons unknown switch((uint16_t) heaters[i].heater_pwm) { case (uint16_t) &OCR0A: TCCR0A |= MASK(COM0A1); @@ -73,10 +73,11 @@ void heater_init() { break; } } - } + + // 0 is a "sane" temperature when we're trying to cool down + heaters_runtime[i].sane_temperature = 0; // read factors from eeprom - for (i = 0; i < NUM_HEATERS; i++) { heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor); heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor); heaters_pid[i].d_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_d_factor); @@ -103,15 +104,18 @@ void heater_save_settings() { } void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { - // now for heater stuff - int16_t t_error = target_temp - current_temp; + int16_t heater_p; + int16_t heater_d; + uint8_t pid_output; + + int16_t t_error = target_temp - current_temp; heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp; heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1); // PID stuff // proportional - heaters_runtime[h].heater_p = t_error; + heater_p = t_error; // integral heaters_runtime[h].heater_i += t_error; @@ -123,31 +127,87 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { // derivative // note: D follows temp rather than error so there's no large derivative when the target changes - heaters_runtime[h].heater_d = current_temp - heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer]; + heater_d = heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer] - current_temp; // combine factors int32_t pid_output_intermed = ( ( - (((int32_t) heaters_runtime[h].heater_p) * heaters_pid[h].p_factor) + + (((int32_t) heater_p) * heaters_pid[h].p_factor) + (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + - (((int32_t) heaters_runtime[h].heater_d) * heaters_pid[h].d_factor) + (((int32_t) heater_d) * heaters_pid[h].d_factor) ) / PID_SCALE ); // rebase and limit factors if (pid_output_intermed > 255) - heaters_runtime[h].pid_output = 255; + pid_output = 255; else if (pid_output_intermed < 0) - heaters_runtime[h].pid_output = 0; + pid_output = 0; else - heaters_runtime[h].pid_output = pid_output_intermed & 0xFF; + pid_output = pid_output_intermed & 0xFF; #ifdef DEBUG if (debug_flags & DEBUG_PID) - sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heaters_runtime[h].heater_p, heaters_pid[h].p_factor, (int32_t) heaters_runtime[h].heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heaters_runtime[h].heater_d, heaters_pid[h].d_factor, (int32_t) heaters_runtime[h].heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, heaters_runtime[h].pid_output); + sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heater_p, heaters_pid[h].p_factor, (int32_t) heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heater_d, heaters_pid[h].d_factor, (int32_t) heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, pid_output); #endif - heater_set(h, heaters_runtime[h].pid_output); + #ifdef HEATER_SANITY_CHECK + // check heater sanity + // implementation is a moving window with some slow-down to compensate for thermal mass + if (target_temp > (current_temp + TEMP_HYSTERESIS)) { + // heating + if (current_temp > heaters_runtime[h].sane_temperature) + // hotter than sane- good since we're heating unless too hot + heaters_runtime[h].sane_temperature = current_temp; + else { + if (heaters_runtime[h].sanity_counter < 40) + heaters_runtime[h].sanity_counter++; + else { + heaters_runtime[h].sanity_counter = 0; + // ratchet up expected temp + heaters_runtime[h].sane_temperature++; + } + } + // limit to target, so if we overshoot by too much for too long an error is flagged + if (heaters_runtime[h].sane_temperature > target_temp) + heaters_runtime[h].sane_temperature = target_temp; + } + else if (target_temp < (current_temp - TEMP_HYSTERESIS)) { + // cooling + if (current_temp < heaters_runtime[h].sane_temperature) + // cooler than sane- good since we're cooling + heaters_runtime[h].sane_temperature = current_temp; + else { + if (heaters_runtime[h].sanity_counter < 125) + heaters_runtime[h].sanity_counter++; + else { + heaters_runtime[h].sanity_counter = 0; + // ratchet down expected temp + heaters_runtime[h].sane_temperature--; + } + } + // if we're at or below 60 celsius, don't freak out if we can't drop any more. + if (current_temp <= 240) + heaters_runtime[h].sane_temperature = current_temp; + // limit to target, so if we don't cool down for too long an error is flagged + else if (heaters_runtime[h].sane_temperature < target_temp) + heaters_runtime[h].sane_temperature = target_temp; + } + // we're within HYSTERESIS of our target + else { + heaters_runtime[h].sane_temperature = current_temp; + heaters_runtime[h].sanity_counter = 0; + } + + // compare where we're at to where we should be + if (labs(current_temp - heaters_runtime[h].sane_temperature) > TEMP_HYSTERESIS) { + // no change, or change in wrong direction for a long time- heater is broken! + pid_output = 0; + sersendf_P(PSTR("!! heater %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter); + } + #endif + + heater_set(h, pid_output); } void heater_set(uint8_t index, uint8_t value) { From cb4e157d626cd01cda40a2957a0b9f449bb5a08e Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 00:52:14 +1100 Subject: [PATCH 48/82] move TICK_TIME to config.h, add TICK_TIME_MS --- config.h.dist | 6 ++++++ timer.c | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/config.h.dist b/config.h.dist index ffaf896..d0708dc 100644 --- a/config.h.dist +++ b/config.h.dist @@ -341,6 +341,12 @@ struct { */ #define STEP_INTERRUPT_INTERRUPTIBLE 1 +/* + how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535) +*/ +#define TICK_TIME 2 MS +#define TICK_TIME_MS (TICK_TIME / (F_CPU / 1000)) + /* temperature history count. This is how many temperature readings to keep in order to calculate derivative in PID loop higher values make PID derivative term more stable at the expense of reaction time diff --git a/timer.c b/timer.c index 2390ff0..6ac461d 100644 --- a/timer.c +++ b/timer.c @@ -11,9 +11,6 @@ uint8_t clock_counter_250ms = 0; uint8_t clock_counter_1s = 0; volatile uint8_t clock_flag = 0; -// how often we overflow and update our clock; with F_CPU=16MHz, max is < 4.096ms (TICK_TIME = 65535) -#define TICK_TIME 2 MS - // timer overflow, happens every TICK_TIME ISR(TIMER1_CAPT_vect) { /* @@ -29,7 +26,7 @@ ISR(TIMER1_CAPT_vect) { /* clock stuff */ - clock_counter_10ms += (TICK_TIME / (F_CPU / 1000)); + clock_counter_10ms += TICK_TIME_MS; if (clock_counter_10ms >= 10) { clock_counter_10ms -= 10; clock_flag |= CLOCK_FLAG_10MS; From 7dc8f8d8ffd9d90c4c4d43e24e83d7a3004784cc Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 00:55:07 +1100 Subject: [PATCH 49/82] make sensor and heater structs visually smaller --- config.h.dist | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/config.h.dist b/config.h.dist index d0708dc..aa9f52f 100644 --- a/config.h.dist +++ b/config.h.dist @@ -228,11 +228,8 @@ struct { uint8_t heater_index; } temp_sensors[NUM_TEMP_SENSORS] = { - { - TT_INTERCOM, - 0, - 0 - } + // type pin heater + { TT_INTERCOM, 0, 0 } }; #endif @@ -269,11 +266,8 @@ struct { volatile uint8_t *heater_pwm; } heaters[NUM_HEATERS]/* = { - { - &PORTD, - PIND6, - &OCR0A - } + // port pin pwm + { &PORTD, PIND6, &OCR0A } }*/; #endif From e2063137b51f5b0ca0c97d973eaf8fa053b3ae48 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 09:51:46 +1100 Subject: [PATCH 50/82] add GEN3 and HOST defines to config.h --- config.h.dist | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/config.h.dist b/config.h.dist index aa9f52f..4d63b40 100644 --- a/config.h.dist +++ b/config.h.dist @@ -20,6 +20,16 @@ * * \***************************************************************************/ +/* + Are you using the official GEN3 motherboard with separate extruder controller? +*/ +#define GEN3 + +/* + This is the motherboard, as opposed to the extruder. See extruder/ directory for GEN3 extruder firmware +*/ +#define HOST + /* Values reflecting the gearing of your machine. All numbers are fixed point integers, so no more than 3 digits to the right of the decimal point, please :-) @@ -113,7 +123,6 @@ * * \***************************************************************************/ - /* Machine Pin Definitions - make sure to avoid duplicate usage of a pin @@ -229,7 +238,7 @@ struct { } temp_sensors[NUM_TEMP_SENSORS] = { // type pin heater - { TT_INTERCOM, 0, 0 } + { TT_INTERCOM, 0, 255 } }; #endif From 1f76745c9da2d54f41943330733c4da3d1d3fd4e Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 09:52:01 +1100 Subject: [PATCH 51/82] slightly stricter sanity check for associated heater index --- temp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/temp.c b/temp.c index 8023b8f..22ca721 100644 --- a/temp.c +++ b/temp.c @@ -228,7 +228,7 @@ void temp_sensor_tick() { all_within_range = 0; } - if (temp_sensors[i].heater_index != 255) { + if (temp_sensors[i].heater_index < NUM_HEATERS) { heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp); } } From 67fca36ecb13fb790ad144813aea2da90383f6dc Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 09:59:32 +1100 Subject: [PATCH 52/82] remove redundant variable --- temp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/temp.c b/temp.c index 22ca721..3677ac2 100644 --- a/temp.c +++ b/temp.c @@ -110,7 +110,7 @@ void temp_init() { } void temp_sensor_tick() { - uint8_t i = 0, all_within_range = 1; + uint8_t i = 0; for (; i < NUM_TEMP_SENSORS; i++) { if (temp_sensors_runtime[i].next_read_time) { temp_sensors_runtime[i].next_read_time--; @@ -225,7 +225,6 @@ void temp_sensor_tick() { } else { temp_sensors_runtime[i].temp_residency = 0; - all_within_range = 0; } if (temp_sensors[i].heater_index < NUM_HEATERS) { @@ -257,6 +256,7 @@ uint16_t temp_get(uint8_t index) { return temp_sensors_runtime[index].last_read_temp; } +// extruder doesn't have sersendf_P #ifndef EXTRUDER void temp_print(uint8_t index) { uint8_t c = 0; From cac3cb722195e98f2a2b8da98338f4b3d403d1bb Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 10:06:59 +1100 Subject: [PATCH 53/82] add comments re mcu type, minor changes to arduino.h --- arduino.h | 10 +++++----- config.h.dist | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arduino.h b/arduino.h index d80089b..476ba1b 100644 --- a/arduino.h +++ b/arduino.h @@ -32,8 +32,10 @@ #define READ(IO) _READ(IO) #define WRITE(IO, v) _WRITE(IO, v) #define TOGGLE(IO) _TOGGLE(IO) + #define SET_INPUT(IO) _SET_INPUT(IO) #define SET_OUTPUT(IO) _SET_OUTPUT(IO) + #define GET_INPUT(IO) _GET_INPUT(IO) #define GET_OUTPUT(IO) _GET_OUTPUT(IO) @@ -41,21 +43,19 @@ ports and functions added as necessary or if I feel like it- not a comprehensive list! - - probably needs some #ifdefs for various chip types */ #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) #include "arduino_168_328p.h" -#endif /* _AVR_ATmega{168,328,328P}__) */ +#endif /* _AVR_ATmega{168,328,328P}__ */ #if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) #include "arduino_644.h" -#endif +#endif /* _AVR_ATmega{644,644P,644PA}__ */ #if defined (__AVR_ATmega1280__) #include "arduino_1280.h" -#endif /* __AVR_ATmega1280__) */ +#endif /* __AVR_ATmega1280__ */ #ifndef DIO0_PIN #error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please tell us via the forum thread diff --git a/config.h.dist b/config.h.dist index 4d63b40..e11ed24 100644 --- a/config.h.dist +++ b/config.h.dist @@ -20,6 +20,12 @@ * * \***************************************************************************/ +/* + Set your microcontroller type in Makefile! atmega168/atmega328p/atmega644p/atmega1280 + + If you want to port this to a new chip, start off with arduino.h and see how you go. +*/ + /* Are you using the official GEN3 motherboard with separate extruder controller? */ From dfb5de7b33fa5d81b5248d934efddf31561ebf67 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 11 Nov 2010 15:03:51 +1100 Subject: [PATCH 54/82] list temp sensor types in config --- config.h.dist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.h.dist b/config.h.dist index e11ed24..ea94fac 100644 --- a/config.h.dist +++ b/config.h.dist @@ -233,6 +233,9 @@ * for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * * 255 * * * +* Types are same as TEMP_ list above- TT_MAX6675, TT_THERMISTOR, TT_AD595, * +* TT_INTERCOM. See list in temp.c. * +* * \***************************************************************************/ #ifdef TEMP_C From 3b6326911a864617b785f3f5ff19df84dc791765 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Fri, 12 Nov 2010 12:51:13 +1100 Subject: [PATCH 55/82] use x_enable and friends more, use sersendf_P more --- gcode_process.c | 104 +++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 72 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index e701856..eda112f 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -163,9 +163,8 @@ void process_gcode_command() { // unknown gcode: spit an error default: - serial_writestr_P(PSTR("E: Bad G-code ")); - serwrite_uint8(next_target.G); - serial_writechar('\n'); + sersendf_P(PSTR("E: Bad G-code %d"), next_target.G); + // newline is sent from gcode_parse after we return } } else if (next_target.seen_M) { @@ -260,11 +259,13 @@ void process_gcode_command() { // M113- extruder PWM // M114- report XYZEF to host case 114: - sersendf_P(PSTR("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); + sersendf_P(PSTR("X:%ld,Y:%ld,Z:%ld,E:%ld,F:%ld"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); + // newline is sent from gcode_parse after we return break; // M115- capabilities string case 115: - sersendf_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d\n"), 1, NUM_TEMP_SENSORS, NUM_HEATERS); + sersendf_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d"), 1, NUM_TEMP_SENSORS, NUM_HEATERS); + // newline is sent from gcode_parse after we return break; #if NUM_HEATERS > 0 @@ -302,77 +303,43 @@ void process_gcode_command() { // M190- power on case 190: power_on(); - #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 0); - #endif - #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 0); - #endif - #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 0); - #endif + x_enable(); + y_enable(); + z_enable(); steptimeout = 0; break; // M191- power off case 191: - #ifdef X_ENABLE_PIN - WRITE(X_ENABLE_PIN, 1); - #endif - #ifdef Y_ENABLE_PIN - WRITE(Y_ENABLE_PIN, 1); - #endif - #ifdef Z_ENABLE_PIN - WRITE(Z_ENABLE_PIN, 1); - #endif + x_disable(); + y_disable(); + z_disable(); power_off(); break; - #ifdef DEBUG + #ifdef DEBUG // M140- echo off case 140: debug_flags &= ~DEBUG_ECHO; - serial_writestr_P(PSTR("Echo off\n")); + serial_writestr_P(PSTR("Echo off")); + // newline is sent from gcode_parse after we return break; // M141- echo on case 141: debug_flags |= DEBUG_ECHO; - serial_writestr_P(PSTR("Echo on\n")); + serial_writestr_P(PSTR("Echo on")); + // newline is sent from gcode_parse after we return break; - // DEBUG: return current position + // DEBUG: return current position, end position, queue case 250: - serial_writestr_P(PSTR("{X:")); - serwrite_int32(current_position.X); - serial_writestr_P(PSTR(",Y:")); - serwrite_int32(current_position.Y); - serial_writestr_P(PSTR(",Z:")); - serwrite_int32(current_position.Z); - serial_writestr_P(PSTR(",E:")); - serwrite_int32(current_position.E); - serial_writestr_P(PSTR(",F:")); - serwrite_int32(current_position.F); - serial_writestr_P(PSTR(",c:")); - serwrite_uint32(movebuffer[mb_tail].c); - serial_writestr_P(PSTR("}\n")); - - serial_writestr_P(PSTR("{X:")); - serwrite_int32(movebuffer[mb_tail].endpoint.X); - serial_writestr_P(PSTR(",Y:")); - serwrite_int32(movebuffer[mb_tail].endpoint.Y); - serial_writestr_P(PSTR(",Z:")); - serwrite_int32(movebuffer[mb_tail].endpoint.Z); - serial_writestr_P(PSTR(",E:")); - serwrite_int32(movebuffer[mb_tail].endpoint.E); - serial_writestr_P(PSTR(",F:")); - serwrite_int32(movebuffer[mb_tail].endpoint.F); - serial_writestr_P(PSTR(",c:")); - #ifdef ACCELERATION_REPRAP - serwrite_uint32(movebuffer[mb_tail].end_c); - #else - serwrite_uint32(movebuffer[mb_tail].c); - #endif - serial_writestr_P(PSTR("}\n")); - + sersendf_P(PSTR("{X:%ld,Y:%ld,Z:%ld,E:%ld,F:%lu,c:%lu}\t{X:%ld,Y:%ld,Z:%ld,E:%ld,F:%lu,c:%lu}\t"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F, movebuffer[mb_tail].c, movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F, + #ifdef ACCELERATION_REPRAP + movebuffer[mb_tail].end_c + #else + movebuffer[mb_tail].c + #endif + ); + print_queue(); break; @@ -384,27 +351,20 @@ void process_gcode_command() { serwrite_hex8(*(volatile uint8_t *)(next_target.S)); next_target.S++; } - serial_writechar('\n'); + // newline is sent from gcode_parse after we return break; // DEBUG: write arbitrary memory locatiom case 254: -// serwrite_hex8(next_target.S); -// serial_writechar(':'); -// serwrite_hex8(*(volatile uint8_t *)(next_target.S)); -// serial_writestr_P(PSTR("->")); -// serwrite_hex8(next_target.P); -// serial_writechar('\n'); - sersendf_P(PSTR("%x:%x->%x\n"), next_target.S, *(volatile uint8_t *)(next_target.S), next_target.P); + sersendf_P(PSTR("%x:%x->%x"), next_target.S, *(volatile uint8_t *)(next_target.S), next_target.P); (*(volatile uint8_t *)(next_target.S)) = next_target.P; + // newline is sent from gcode_parse after we return break; - #endif /* DEBUG */ + #endif /* DEBUG */ // unknown mcode: spit an error default: -/* serial_writestr_P(PSTR("E: Bad M-code ")); - serwrite_uint8(next_target.M); - serial_writechar('\n');*/ - sersendf_P(PSTR("E: Bad M-code %d\n"), next_target.M); + sersendf_P(PSTR("E: Bad M-code %d"), next_target.M); + // newline is sent from gcode_parse after we return } } } From 8e4b35b0da0b68bef87f78b8f9e3baeee1a1e5f8 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 20 Nov 2010 12:23:38 +1100 Subject: [PATCH 56/82] defines for PT100 sensors- actual code to come later --- config.h.dist | 4 +++- temp.c | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config.h.dist b/config.h.dist index ea94fac..ac28570 100644 --- a/config.h.dist +++ b/config.h.dist @@ -211,6 +211,7 @@ // #define TEMP_MAX6675 // #define TEMP_THERMISTOR // #define TEMP_AD595 +// #define TEMP_PT100 #define TEMP_INTERCOM // if you selected thermistor or AD595, what pin is it on? (this value only used to fill ANALOG_MASK for you) @@ -285,7 +286,8 @@ struct { } heaters[NUM_HEATERS]/* = { // port pin pwm - { &PORTD, PIND6, &OCR0A } + { &PORTD, PIND6, &OCR0A }, + { &PORTD, PIND5, &OCR0B } }*/; #endif diff --git a/temp.c b/temp.c index 3677ac2..7a044cf 100644 --- a/temp.c +++ b/temp.c @@ -19,6 +19,7 @@ typedef enum { TT_THERMISTOR, TT_MAX6675, TT_AD595, + TT_PT100, TT_INTERCOM } temp_types; @@ -206,6 +207,12 @@ void temp_sensor_tick() { break; #endif /* TEMP_AD595 */ + #ifdef TEMP_PT100 + case TT_PT100: + #warning TODO: PT100 code + break + #endif /* TEMP_PT100 */ + #ifdef GEN3 case TT_INTERCOM: temp = get_read_cmd() << 2; From 4c7231aa8bbc5eeb06a802434af1f963c01ce402 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 20 Nov 2010 12:24:04 +1100 Subject: [PATCH 57/82] minor comment changes --- gcode_parse.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 343656c..5f96ba3 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -14,13 +14,13 @@ /* Switch user friendly values to coding friendly values - This also affects the possible build volume. We have +-2^31 numbers available and as we internally measure position in steps and use a precision factor of 1000, this translates into a possible range of + This also affects the possible build volume. We have +/- 2^31 numbers available and as we internally measure position in steps and use a precision factor of 1000, this translates into a possible range of 2^31 mm / STEPS_PER_MM_x / 1000 for each axis. For a M6 threaded rod driven machine and 1/16 microstepping this evaluates to - 2^31 mm / 200 / 1 / 16 / 1000 = 671 mm, + 2^31 mm / 200 / 16 / 1000 = 671 mm, which is about the worst case we have. All other machines have a bigger build volume. */ @@ -390,13 +390,13 @@ void gcode_parse_char(uint8_t c) { } } -/**************************************************************************** +/***************************************************************************\ * * * Request a resend of the current line - used from various places. * * * * Relies on the global variable next_target.N being valid. * * * -****************************************************************************/ +\***************************************************************************/ void request_resend(void) { serial_writestr_P(PSTR("rs ")); From ad52220855b2527423c9610142867b3d76a68ab1 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 20 Nov 2010 13:10:44 +1100 Subject: [PATCH 58/82] check for HEATER_SANITY_CHECK before trying to use sanity checking variables --- heater.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/heater.c b/heater.c index e71ca9b..6e050ca 100644 --- a/heater.c +++ b/heater.c @@ -6,7 +6,9 @@ #include "arduino.h" #include "debug.h" +#ifndef EXTRUDER #include "sersendf.h" +#endif #define HEATER_C #include "config.h" @@ -74,8 +76,10 @@ void heater_init() { } } - // 0 is a "sane" temperature when we're trying to cool down - heaters_runtime[i].sane_temperature = 0; + #ifdef HEATER_SANITY_CHECK + // 0 is a "sane" temperature when we're trying to cool down + heaters_runtime[i].sane_temperature = 0; + #endif // read factors from eeprom heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor); From e94482c00c8d9759c07a30c22f534a9224556ab7 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 20 Nov 2010 13:11:53 +1100 Subject: [PATCH 59/82] move defines from Makefile to config.h.dist --- Makefile | 6 +++-- analog.c | 5 ++--- config.h.dist | 54 +++++++++++++++++++++++++++++++-------------- extruder/intercom.c | 3 +-- temp.c | 22 +++++++++--------- 5 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index afede04..802f17b 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ MCU_TARGET = atmega644p # MCU_TARGET = atmega1280 -F_CPU = 16000000L +# F_CPU = 16000000L ############################################################################## # # @@ -59,7 +59,7 @@ F_CPU = 16000000L # # ############################################################################## -DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3 +# DEFS = -DF_CPU=$(F_CPU) -DHOST -DGEN3 # DEFS += "-DDEBUG=1" ############################################################################## @@ -133,6 +133,8 @@ size: $(PROGRAM).elf config.h: config.h.dist @echo "Please review config.h, as config.h.dist is more recent." + @echo + @diff -bBEuF '^. [[:digit:]]. [[:upper:]]' config.h config.h.dist @false %.o: %.c config.h Makefile diff --git a/analog.c b/analog.c index 346551b..2cf3e00 100644 --- a/analog.c +++ b/analog.c @@ -3,9 +3,8 @@ #include #ifndef ANALOG_MASK - #warning define ANALOG_MASK as a bitmask of all the analog channels you wish to use - #warning defining ANALOG_MASK as zero will prevent the analog subsystem from starting - #error ANALOG_MASK not defined + #warning ANALOG_MASK not defined - analog subsystem disabled + #define ANALOG_MASK 0 #endif uint8_t adc_running_mask, adc_counter; diff --git a/config.h.dist b/config.h.dist index ac28570..fc5c322 100644 --- a/config.h.dist +++ b/config.h.dist @@ -26,6 +26,13 @@ If you want to port this to a new chip, start off with arduino.h and see how you go. */ +/* + CPU clock rate +*/ +#ifndef F_CPU + #define F_CPU 16000000L +#endif + /* Are you using the official GEN3 motherboard with separate extruder controller? */ @@ -76,30 +83,40 @@ #define E_STARTSTOP_STEPS 20 + /***************************************************************************\ * * * 2. ACCELERATION * * * +* IMPORTANT: choose only one! These algorithms choose when to step, trying * +* to use more than one will have undefined and probably * +* disastrous results! * +* * \***************************************************************************/ /* acceleration, reprap style. Each movement starts at the speed of the previous command and accelerates or decelerates linearly to reach target speed at the end of the movement. - Can also be set in Makefile */ // #define ACCELERATION_REPRAP + /* acceleration and deceleration ramping. Each movement starts at (almost) no speed, linearly accelerates to target speed and decelerates just in time to smoothly stop at the target. alternative to ACCELERATION_REPRAP - Can also be set in Makefile */ // #define ACCELERATION_RAMPING +// how fast to accelerate when using ACCELERATION_RAMPING +// smaller values give quicker acceleration +// valid range = 1 to 8,000,000; 500,000 is a good starting point +#define ACCELERATION_STEEPNESS 500000 + + /* temporal step algorithm - This algorithm causes the timer to fire when any axis needs to step, instead of synchronising to the axis with the most steps. + This algorithm causes the timer to fire when any axis needs to step, instead of synchronising to the axis with the most steps ala bresenham. This algorithm is not a type of acceleration, and I haven't worked out how to integrate acceleration with it. However it does control step timing, so acceleration algorithms seemed appropriate @@ -111,16 +128,6 @@ */ // #define ACCELERATION_TEMPORAL -// how fast to accelerate when using ACCELERATION_RAMPING -// smaller values give quicker acceleration -// valid range = 1 to 8,000,000; 500,000 is a good starting point -#define ACCELERATION_STEEPNESS 500000 - -#ifdef ACCELERATION_REPRAP - #ifdef ACCELERATION_RAMPING - #error "Can't use ACCELERATION_REPRAP and ACCELERATION_RAMPING together." - #endif -#endif /***************************************************************************\ @@ -161,7 +168,9 @@ #define PS_ON_PIN DIO9 #else - // this is official reprap motherboard pinout + /* + this is the official gen3 reprap motherboard pinout + */ #define TX_ENABLE_PIN DIO12 #define RX_ENABLE_PIN DIO13 @@ -190,6 +199,8 @@ #define SD_WRITE_PROTECT DIO3 #endif + + /***************************************************************************\ * * * 4. TEMPERATURE SENSORS * @@ -217,7 +228,7 @@ // if you selected thermistor or AD595, what pin is it on? (this value only used to fill ANALOG_MASK for you) #define TEMP_PIN_CHANNEL AIO0_PIN -// ANALOG_MASK is a bitmask of all analog channels used- if you use more than one analog input, bitwise-or them all together +// ANALOG_MASK is a bitmask of all analog channels used- if you use more than one analog input (more than one temp sensor?), bitwise-or them all together #define ANALOG_MASK MASK(TEMP_PIN_CHANNEL) // how many temperature sensors do you have? @@ -232,10 +243,10 @@ * do not affect firmware operation * * * * for GEN3 set temp_type to TT_INTERCOM, temp_pin to 0 and heater index to * -* 255 * +* 255 - the extruder manages the heater for us * * * * Types are same as TEMP_ list above- TT_MAX6675, TT_THERMISTOR, TT_AD595, * -* TT_INTERCOM. See list in temp.c. * +* TT_PT100, TT_INTERCOM. See list in temp.c. * * * \***************************************************************************/ @@ -324,6 +335,14 @@ struct { * * \***************************************************************************/ +/* + DEBUG + enables /heaps/ of extra output, and some extra M-codes. + WARNING: this WILL break most host-side talkers that expect particular responses from firmware such as reprap host and replicatorG + use with serial terminal or other suitable talker only. +*/ +// #define DEBUG + /* move buffer size, in number of moves note that each move takes a fair chunk of ram (69 bytes as of this writing) so don't make the buffer too big - a bigger serial readbuffer may help more than increasing this unless your gcodes are more than 70 characters long on average. @@ -379,6 +398,7 @@ struct { * * * list of PWM-able pins and corresponding timers * * timer1 is used for step timing so don't use OC1A/OC1B * +* they are omitted from this listing for that reason * * * * For the atmega168/328, timer/pin mappings are as follows * * * diff --git a/extruder/intercom.c b/extruder/intercom.c index 35cd1f3..7cab163 100644 --- a/extruder/intercom.c +++ b/extruder/intercom.c @@ -1,5 +1,3 @@ -#ifdef GEN3 - #include "intercom.h" #include @@ -7,6 +5,7 @@ #include "config.h" #include "delay.h" +#ifdef GEN3 #define INTERCOM_BAUD 57600 #define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0) diff --git a/temp.c b/temp.c index 7a044cf..4809218 100644 --- a/temp.c +++ b/temp.c @@ -4,17 +4,6 @@ #include #include -#include "arduino.h" -#include "delay.h" -#include "debug.h" -#ifndef EXTRUDER - #include "sersendf.h" -#endif -#include "heater.h" -#ifdef GEN3 - #include "intercom.h" -#endif - typedef enum { TT_THERMISTOR, TT_MAX6675, @@ -31,6 +20,17 @@ typedef enum { #define TEMP_C #include "config.h" +#include "arduino.h" +#include "delay.h" +#include "debug.h" +#ifndef EXTRUDER + #include "sersendf.h" +#endif +#include "heater.h" +#ifdef GEN3 + #include "intercom.h" +#endif + // this struct holds the runtime sensor data- read temperatures, targets, etc struct { temp_flags_enum temp_flags; From d6644af18f90d530d0a3a1dd6c573b3579000626 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Wed, 24 Nov 2010 09:37:01 +1100 Subject: [PATCH 60/82] cause M101/M103 to work with DC extruders --- gcode_process.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index eda112f..19591f8 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -174,7 +174,9 @@ void process_gcode_command() { if (temp_achieved() == 0) { enqueue(NULL); } - #if E_STARTSTOP_STEPS > 0 + #ifdef DC_EXTRUDER + heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM); + #elif E_STARTSTOP_STEPS > 0 do { // backup feedrate, move E very quickly then restore feedrate backup_f = startpoint.F; @@ -189,7 +191,9 @@ void process_gcode_command() { // M103- extruder off case 103: - #if E_STARTSTOP_STEPS > 0 + #ifdef DC_EXTRUDER + heater_set(DC_EXTRUDER, 0); + #elif E_STARTSTOP_STEPS > 0 do { // backup feedrate, move E very quickly then restore feedrate backup_f = startpoint.F; From 402ebbbddff666804e7ad2feb9004fba61293bf7 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 09:48:28 +1100 Subject: [PATCH 61/82] move step/dir/endstop primitives to pinio --- dda.c | 60 ---------------------------- pinio.c | 2 +- pinio.h | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 116 insertions(+), 68 deletions(-) diff --git a/dda.c b/dda.c index 87d6183..ca93e39 100644 --- a/dda.c +++ b/dda.c @@ -17,66 +17,6 @@ #include "heater.h" #endif -/* - X Stepper -*/ - -#define _x_step(st) WRITE(X_STEP_PIN, st) -#define x_step() _x_step(1); -#define x_direction(dir) WRITE(X_DIR_PIN, dir) -#define x_min() READ(X_MIN_PIN) -#ifdef X_MAX_PIN - #define x_max() READ(X_MAX_PIN) -#else - #define x_max() (0) -#endif - -/* - Y Stepper -*/ - -#define _y_step(st) WRITE(Y_STEP_PIN, st) -#define y_step() _y_step(1); -#define y_direction(dir) WRITE(Y_DIR_PIN, dir) -#define y_min() READ(Y_MIN_PIN) -#ifdef Y_MAX_PIN - #define y_max() READ(Y_MAX_PIN) -#else - #define y_max() (0) -#endif - -/* - Z Stepper -*/ - -#define _z_step(st) WRITE(Z_STEP_PIN, st) -#define z_step() _z_step(1); -#define z_direction(dir) WRITE(Z_DIR_PIN, dir) -#define z_min() READ(Z_MIN_PIN) -#ifdef Z_MAX_PIN - #define z_max() READ(Z_MAX_PIN) -#else - #define z_max() (0) -#endif - -/* - Extruder -*/ - -#define _e_step(st) WRITE(E_STEP_PIN, st) -#define e_step() _e_step(1); -#define e_direction(dir) WRITE(E_DIR_PIN, dir) - -/* - End Step - All Steppers - (so we don't have to delay in interrupt context) -*/ - -#ifndef DC_EXTRUDER - #define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) -#else - #define unstep() do { _x_step(0); _y_step(0); _z_step(0); } while (0) -#endif /* Used in distance calculation during DDA setup */ diff --git a/pinio.c b/pinio.c index f21fe66..8d89ed1 100644 --- a/pinio.c +++ b/pinio.c @@ -12,7 +12,7 @@ void power_off() { #endif #ifdef STEPPER_ENABLE_PIN - SET_INPUT(STEPPER_ENABLE_PIN); + WRITE(STEPPER_ENABLE_PIN, STEPPER_ENABLE_INVERT ^ 1) #endif #ifdef PS_ON_PIN SET_INPUT(PS_ON_PIN); diff --git a/pinio.h b/pinio.h index ab40014..624668c 100644 --- a/pinio.h +++ b/pinio.h @@ -1,12 +1,59 @@ #ifndef _PINIO_H #define _PINIO_H +#ifndef X_INVERT_DIR + #define X_INVERT_DIR 0 +#endif +#ifndef X_INVERT_MIN + #define X_INVERT_MIN 0 +#endif +#ifndef X_INVERT_MAX + #define X_INVERT_MAX 0 +#endif +#ifndef X_INVERT_ENABLE + #define X_INVERT_ENABLE 0 +#endif + +#ifndef Y_INVERT_DIR + #define Y_INVERT_DIR 0 +#endif +#ifndef Y_INVERT_MIN + #define Y_INVERT_MIN 0 +#endif +#ifndef Y_INVERT_MAX + #define Y_INVERT_MAX 0 +#endif +#ifndef Y_INVERT_ENABLE + #define Y_INVERT_ENABLE 0 +#endif + +#ifndef Z_INVERT_DIR + #define Z_INVERT_DIR 0 +#endif +#ifndef Z_INVERT_MIN + #define Z_INVERT_MIN 0 +#endif +#ifndef Z_INVERT_MAX + #define Z_INVERT_MAX 0 +#endif +#ifndef Z_INVERT_ENABLE + #define Z_INVERT_ENABLE 0 +#endif + +#ifndef E_INVERT_DIR + #define E_INVERT_DIR 0 +#endif + +#ifndef STEPPER_ENABLE_INVERT + #define STEPPER_ENABLE_INVERT 0 +#endif + /* Power */ #ifdef STEPPER_ENABLE_PIN - #define power_on() do { WRITE(STEPPER_ENABLE_PIN, 0); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0) + #define power_on() do { WRITE(STEPPER_ENABLE_PIN, STEPPER_ENABLE_INVERT); SET_OUTPUT(STEPPER_ENABLE_PIN); } while (0) #elif defined PS_ON_PIN #define power_on() do { WRITE(PS_ON_PIN, 0); SET_OUTPUT(PS_ON_PIN); } while (0) #else @@ -15,29 +62,90 @@ Power void power_off(void); +/* +X Stepper +*/ + +#define _x_step(st) WRITE(X_STEP_PIN, st) +#define x_step() _x_step(1); +#define x_direction(dir) WRITE(X_DIR_PIN, dir ^ X_INVERT_DIR) +#define x_min() (READ(X_MIN_PIN)?(X_INVERT_MIN ^ 1):X_INVERT_DIR) +#ifdef X_MAX_PIN + #define x_max() (READ(X_MAX_PIN)?(X_INVERT_MAX ^ 1):X_INVERT_MAX) +#else + #define x_max() (0) +#endif + +/* +Y Stepper +*/ + +#define _y_step(st) WRITE(Y_STEP_PIN, st) +#define y_step() _y_step(1); +#define y_direction(dir) WRITE(Y_DIR_PIN, dir ^ Y_INVERT_DIR) +#define y_min() (READ(Y_MIN_PIN)?(Y_INVERT_MIN ^ 1):Y_INVERT_MIN) +#ifdef Y_MAX_PIN + #define y_max() (READ(Y_MAX_PIN)?(Y_INVERT_MAX ^ 1):Y_INVERT_MAX) +#else + #define y_max() (0) +#endif + +/* +Z Stepper +*/ + +#define _z_step(st) WRITE(Z_STEP_PIN, st) +#define z_step() _z_step(1); +#define z_direction(dir) WRITE(Z_DIR_PIN, dir ^ Z_INVERT_DIR) +#define z_min() (READ(Z_MIN_PIN)?(Z_INVERT_MIN ^ 1):Z_INVERT_MIN) +#ifdef Z_MAX_PIN + #define z_max() (READ(Z_MAX_PIN)?(Z_INVERT_MAX ^ 1):Z_INVERT_MAX) +#else + #define z_max() (0) +#endif + +/* +Extruder +*/ + +#define _e_step(st) WRITE(E_STEP_PIN, st) +#define e_step() _e_step(1); +#define e_direction(dir) WRITE(E_DIR_PIN, dir ^ E_INVERT_DIR) + +/* +End Step - All Steppers +(so we don't have to delay in interrupt context) +*/ + +#ifndef DC_EXTRUDER + #define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) +#else + #define unstep() do { _x_step(0); _y_step(0); _z_step(0); } while (0) +#endif + /* Stepper Enable Pins */ #ifdef X_ENABLE_PIN - #define x_enable() do { WRITE(X_ENABLE_PIN, 0); SET_OUTPUT(X_ENABLE_PIN); } while (0) - #define x_disable() do { WRITE(X_ENABLE_PIN, 1); SET_OUTPUT(X_ENABLE_PIN); } while (0) + #define x_enable() do { WRITE(X_ENABLE_PIN, X_INVERT_ENABLE); SET_OUTPUT(X_ENABLE_PIN); } while (0) + #define x_disable() do { WRITE(X_ENABLE_PIN, X_INVERT_ENABLE ^ 1); SET_OUTPUT(X_ENABLE_PIN); } while (0) #else #define x_enable() do { } while (0) #define x_disable() do { } while (0) #endif #ifdef Y_ENABLE_PIN - #define y_enable() do { WRITE(Y_ENABLE_PIN, 0); SET_OUTPUT(Y_ENABLE_PIN); } while (0) - #define y_disable() do { WRITE(Y_ENABLE_PIN, 1); SET_OUTPUT(Y_ENABLE_PIN); } while (0) + #define y_enable() do { WRITE(Y_ENABLE_PIN, Y_INVERT_ENABLE); SET_OUTPUT(Y_ENABLE_PIN); } while (0) + #define y_disable() do { WRITE(Y_ENABLE_PIN, Y_INVERT_ENABLE ^ 1); SET_OUTPUT(Y_ENABLE_PIN); } while (0) #else #define y_enable() do { } while (0) #define y_disable() do { } while (0) #endif #ifdef Z_ENABLE_PIN - #define z_enable() do { WRITE(Z_ENABLE_PIN, 0); SET_OUTPUT(Z_ENABLE_PIN); } while (0) - #define z_disable() do { WRITE(Z_ENABLE_PIN, 1); SET_OUTPUT(Z_ENABLE_PIN); } while (0) + #define z_enable() do { WRITE(Z_ENABLE_PIN, Z_INVERT_ENABLE); SET_OUTPUT(Z_ENABLE_PIN); } while (0) + #define z_disable() do { WRITE(Z_ENABLE_PIN, Z_INVERT_ENABLE ^ 1); SET_OUTPUT(Z_ENABLE_PIN); } while (0) #else #define z_enable() do { } while (0) #define z_disable() do { } while (0) From a57ba313b865a4a2d39a94b30c2983401b097524 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 09:49:00 +1100 Subject: [PATCH 62/82] implement queue_wait() --- dda_queue.c | 9 +++++++++ dda_queue.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/dda_queue.c b/dda_queue.c index d295c14..ad33992 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -10,6 +10,7 @@ #include "temp.h" #include "delay.h" #include "sersendf.h" +#include "clock.h" uint8_t mb_head = 0; uint8_t mb_tail = 0; @@ -114,3 +115,11 @@ void queue_flush() { // restore interrupt flag SREG = sreg; } + +void queue_wait() { + for (;queue_empty() == 0;) { + ifclock(CLOCK_FLAG_10MS) { + clock_10ms(); + } + } +} diff --git a/dda_queue.h b/dda_queue.h index 46b4a4f..26f0aa2 100644 --- a/dda_queue.h +++ b/dda_queue.h @@ -36,4 +36,7 @@ void print_queue(void); // flush the queue for eg; emergency stop void queue_flush(void); +// wait for queue to empty +void queue_wait(void); + #endif /* _DDA_QUEUE */ From 935eed7f977acaaf1f618dd3b7ed7212c3951476 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 09:50:13 +1100 Subject: [PATCH 63/82] move clock functions from mendel.c to clock.[ch] --- Makefile | 2 +- clock.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ clock.h | 7 +++++++ mendel.c | 36 +----------------------------------- 4 files changed, 54 insertions(+), 36 deletions(-) create mode 100644 clock.c create mode 100644 clock.h diff --git a/Makefile b/Makefile index 802f17b..362b134 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ PROGBAUD = 57600 PROGRAM = mendel -SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c pinio.c +SOURCES = $(PROGRAM).c serial.c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c delay.c intercom.c pinio.c clock.c ARCH = avr- CC = $(ARCH)gcc diff --git a/clock.c b/clock.c new file mode 100644 index 0000000..01bcbf1 --- /dev/null +++ b/clock.c @@ -0,0 +1,45 @@ +#include "clock.h" + +#include "pinio.h" +#include "sersendf.h" +#include "dda_queue.h" +#include "watchdog.h" +#include "temp.h" +#include "timer.h" +#include "debug.h" + +void clock_250ms() { + if (steptimeout > (30 * 4)) { + power_off(); + } + else + steptimeout++; + + ifclock(CLOCK_FLAG_1S) { + if (debug_flags & DEBUG_POSITION) { + // current position + sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); + + // target position + sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F); + + // Queue + print_queue(); + } + // temperature + /* if (temp_get_target()) + temp_print();*/ + } +} + +void clock_10ms() { + // reset watchdog + wd_reset(); + + temp_tick(); + + ifclock(CLOCK_FLAG_250MS) { + clock_250ms(); + } +} + diff --git a/clock.h b/clock.h new file mode 100644 index 0000000..daf4023 --- /dev/null +++ b/clock.h @@ -0,0 +1,7 @@ +#ifndef _CLOCK_H +#define _CLOCK_H + +void clock_250ms(void); +void clock_10ms(void); + +#endif /* _CLOCK_H */ diff --git a/mendel.c b/mendel.c index 0e5d0cc..919822b 100644 --- a/mendel.c +++ b/mendel.c @@ -18,6 +18,7 @@ #include "analog.h" #include "pinio.h" #include "arduino.h" +#include "clock.h" void io_init(void) { // disable modules we don't use @@ -150,41 +151,6 @@ void init(void) { } -void clock_250ms(void) { - if (steptimeout > (30 * 4)) { - power_off(); - } - else - steptimeout++; - - ifclock(CLOCK_FLAG_1S) { - if (debug_flags & DEBUG_POSITION) { - // current position - sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F); - - // target position - sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F); - - // Queue - print_queue(); - } - // temperature -/* if (temp_get_target()) - temp_print();*/ - } -} - -void clock_10ms(void) { - // reset watchdog - wd_reset(); - - temp_tick(); - - ifclock(CLOCK_FLAG_250MS) { - clock_250ms(); - } -} - int main (void) { init(); From e991578e10ce3a7f65942289a70788b4ede78ab5 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 09:51:54 +1100 Subject: [PATCH 64/82] implement G28/G92 as per casainho- see forum thread --- gcode_parse.c | 26 -------- gcode_parse.h | 5 -- gcode_process.c | 165 ++++++++++++++++++++++++++++++------------------ gcode_process.h | 5 ++ 4 files changed, 109 insertions(+), 92 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 5f96ba3..4222bc9 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -87,32 +87,6 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) return r; } -/* - public functions -*/ - -void SpecialMoveXY(int32_t x, int32_t y, uint32_t f) { - TARGET t = startpoint; - t.X = x; - t.Y = y; - t.F = f; - enqueue(&t); -} - -void SpecialMoveZ(int32_t z, uint32_t f) { - TARGET t = startpoint; - t.Z = z; - t.F = f; - enqueue(&t); -} - -void SpecialMoveE(int32_t e, uint32_t f) { - TARGET t = startpoint; - t.E = e; - t.F = f; - enqueue(&t); -} - /**************************************************************************** * * * Character Received - add it to our command * diff --git a/gcode_parse.h b/gcode_parse.h index 7a8dd16..31dafb9 100644 --- a/gcode_parse.h +++ b/gcode_parse.h @@ -63,11 +63,6 @@ extern GCODE_COMMAND next_target; // utility functions int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator); -// this is where we construct a move without a gcode command, useful for gcodes which require multiple moves eg; homing -void SpecialMoveXY(int32_t x, int32_t y, uint32_t f); -void SpecialMoveZ(int32_t z, uint32_t f); -void SpecialMoveE(int32_t e, uint32_t f); - // accept the next character and process it void gcode_parse_char(uint8_t c); diff --git a/gcode_process.c b/gcode_process.c index 19591f8..d8987f5 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -15,6 +15,60 @@ #include "sersendf.h" #include "pinio.h" #include "debug.h" +#include "clock.h" + +/* +public functions +*/ + +void zero_x(void) { + TARGET t = startpoint; + t.X = 0; + t.F = SEARCH_FEEDRATE_X; + enqueue(&t); +} + +void zero_y(void) { + TARGET t = startpoint; + t.Y = 0; + t.F = SEARCH_FEEDRATE_X; + enqueue(&t); +} + +void zero_z(void) { + TARGET t = startpoint; + t.Z = 0; + t.F = SEARCH_FEEDRATE_Z; + enqueue(&t); +} + +void zero_e(void) { + TARGET t = startpoint; + t.E = 0; + enqueue(&t); +} + +// void SpecialMoveXY(int32_t x, int32_t y, uint32_t f) { +// TARGET t = startpoint; +// t.X = x; +// t.Y = y; +// t.F = f; +// enqueue(&t); +// } +// +// void SpecialMoveZ(int32_t z, uint32_t f) { +// TARGET t = startpoint; +// t.Z = z; +// t.F = f; +// enqueue(&t); +// } + +void SpecialMoveE(int32_t e, uint32_t f) { + TARGET t = startpoint; + t.E = e; + t.F = f; + enqueue(&t); +} /**************************************************************************** * * @@ -38,6 +92,7 @@ void process_gcode_command() { // moved to dda.c, end of dda_create() and dda_queue.c, next_move() if (next_target.seen_G) { + uint8_t axisSelected = 0; switch (next_target.G) { // G0 - rapid, unsynchronised motion // since it would be a major hassle to force the dda to not synchronise, just provide a fast feedrate and hope it's close enough to what host expects @@ -62,10 +117,14 @@ void process_gcode_command() { // G4 - Dwell case 4: // wait for all moves to complete - for (;queue_empty() == 0;) - wd_reset(); + queue_wait(); // delay - delay_ms(next_target.P); + for (;next_target.P > 0;next_target.P--) { + ifclock(CLOCK_FLAG_10MS) { + clock_10ms(); + } + delay_ms(1); + } break; // G20 - inches as units @@ -85,61 +144,24 @@ void process_gcode_command() { // G28 - go home case 28: - /* - Home XY first - */ - // hit endstops, no acceleration- we don't care about skipped steps - startpoint.F = MAXIMUM_FEEDRATE_X; - SpecialMoveXY(-250L * STEPS_PER_MM_X, -250L * STEPS_PER_MM_Y, MAXIMUM_FEEDRATE_X); - startpoint.X = startpoint.Y = 0; + queue_wait(); - // move forward a bit - SpecialMoveXY(5 * STEPS_PER_MM_X, 5 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); - - // move back in to endstops slowly - SpecialMoveXY(-20 * STEPS_PER_MM_X, -20 * STEPS_PER_MM_Y, SEARCH_FEEDRATE_X); - - // wait for queue to complete - for (;queue_empty() == 0;) - wd_reset(); - - // this is our home point - startpoint.X = startpoint.Y = current_position.X = current_position.Y = 0; - - /* - Home Z - */ - // hit endstop, no acceleration- we don't care about skipped steps - startpoint.F = MAXIMUM_FEEDRATE_Z; - SpecialMoveZ(-250L * STEPS_PER_MM_Z, MAXIMUM_FEEDRATE_Z); - startpoint.Z = 0; - - // move forward a bit - SpecialMoveZ(5 * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); - - // move back into endstop slowly - SpecialMoveZ(-20L * STEPS_PER_MM_Z, SEARCH_FEEDRATE_Z); - - // wait for queue to complete - for (;queue_empty() == 0;) - wd_reset(); - - // this is our home point - startpoint.Z = current_position.Z = 0; - - /* - Home E - */ - // extruder only runs one way and we have no "endstop", just set this point as home - startpoint.E = current_position.E = 0; - - /* - Home F - */ - - // F has been left at SEARCH_FEEDRATE_Z by the last move, this is a usable "home" - // uncomment the following or substitute if you prefer a different default feedrate - // startpoint.F = SEARCH_FEEDRATE_Z + if (next_target.seen_X) { + zero_x(); + axisSelected = 1; + } + if (next_target.seen_Y) { + zero_y(); + axisSelected = 1; + } + if (next_target.seen_Z) { + zero_z(); + axisSelected = 1; + } + if (next_target.seen_E) { + zero_e(); + axisSelected = 1; + } break; @@ -155,10 +177,31 @@ void process_gcode_command() { // G92 - set home case 92: - startpoint.X = startpoint.Y = startpoint.Z = startpoint.E = - current_position.X = current_position.Y = current_position.Z = current_position.E = 0; - startpoint.F = - current_position.F = SEARCH_FEEDRATE_Z; + // wait for queue to empty + queue_wait(); + + if (next_target.seen_X) { + startpoint.X = current_position.X = next_target.target.X; + axisSelected = 1; + } + if (next_target.seen_Y) { + startpoint.Y = current_position.Y = next_target.target.Y; + axisSelected = 1; + } + if (next_target.seen_Z) { + startpoint.Z = current_position.Z = next_target.target.Z; + axisSelected = 1; + } + if (next_target.seen_E) { + startpoint.E = current_position.E = next_target.target.E; + axisSelected = 1; + } + if (axisSelected == 0) { + startpoint.X = current_position.X = + startpoint.Y = current_position.Y = + startpoint.Z = current_position.Z = + startpoint.E = current_position.E = 0; + } break; // unknown gcode: spit an error diff --git a/gcode_process.h b/gcode_process.h index b872b5e..52557ce 100644 --- a/gcode_process.h +++ b/gcode_process.h @@ -3,6 +3,11 @@ #include "gcode_parse.h" +// this is where we construct a move without a gcode command, useful for gcodes which require multiple moves eg; homing +void SpecialMoveXY(int32_t x, int32_t y, uint32_t f); +void SpecialMoveZ(int32_t z, uint32_t f); +void SpecialMoveE(int32_t e, uint32_t f); + // when we have a whole line, feed it to this void process_gcode_command(void); From a0d20958c3cada92a0e72602605c2732bf389152 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 09:55:29 +1100 Subject: [PATCH 65/82] add resource URIs to README --- README | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README b/README index ee5de4d..cd05cf9 100644 --- a/README +++ b/README @@ -98,6 +98,15 @@ The fixed-point stuff is fun, although we have to manually ensure that the decim The PID code in heater.c is probably quite generalisable, and seems to work well when tuned. Google knows of plenty of PID tuning guides. +############################################################################## +# # +# Resources # +# # +############################################################################## + +Forum thread: http://forums.reprap.org/read.php?147,33082 +Source Repository: http://github.com/triffid/FiveD_on_Arduino +Wiki Page: http://objects.reprap.org/wiki/FiveD_on_Arduino ############################################################################## # # @@ -111,6 +120,9 @@ This is the analog subsystem. Only used if you have a thermistor or ad595 *** arduino.h, arduino_[chip].h Pin mappings and helper functions for various atmegas +*** clock.[ch] +Regular functions that run in main loop rather than an interrupt + *** config.h.dist, config.h Configuration for your electronics and hardware. Copy config.h.dist to config.h, edit config.h to suit From 29391e64e7fa44197fba1a49868d99eda49f45c1 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 10:30:12 +1100 Subject: [PATCH 66/82] add new function prototypes to gcode_process.h --- gcode_process.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcode_process.h b/gcode_process.h index 52557ce..e78057d 100644 --- a/gcode_process.h +++ b/gcode_process.h @@ -3,9 +3,13 @@ #include "gcode_parse.h" + +void zero_x(void); +void zero_y(void); +void zero_z(void); +void zero_e(void); + // this is where we construct a move without a gcode command, useful for gcodes which require multiple moves eg; homing -void SpecialMoveXY(int32_t x, int32_t y, uint32_t f); -void SpecialMoveZ(int32_t z, uint32_t f); void SpecialMoveE(int32_t e, uint32_t f); // when we have a whole line, feed it to this From 51a419601f0a3a0fd011bd5f4b87e04d16d66241 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 10:30:44 +1100 Subject: [PATCH 67/82] add M2/M3/M5/M7/M9 support --- gcode_process.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index d8987f5..72451f4 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -48,21 +48,6 @@ void zero_e(void) { enqueue(&t); } -// void SpecialMoveXY(int32_t x, int32_t y, uint32_t f) { -// TARGET t = startpoint; -// t.X = x; -// t.Y = y; -// t.F = f; -// enqueue(&t); -// } -// -// void SpecialMoveZ(int32_t z, uint32_t f) { -// TARGET t = startpoint; -// t.Z = z; -// t.F = f; -// enqueue(&t); -// } - void SpecialMoveE(int32_t e, uint32_t f) { TARGET t = startpoint; t.E = e; @@ -212,7 +197,19 @@ void process_gcode_command() { } else if (next_target.seen_M) { switch (next_target.M) { - // M101- extruder on + // M2- program end + case 2: + timer_stop(); + queue_flush(); + x_disable(); + y_disable(); + z_disable(); + power_off(); + for (;;) + wd_reset(); + break; + // M3/M101- extruder on + case 3: case 101: if (temp_achieved() == 0) { enqueue(NULL); @@ -232,7 +229,8 @@ void process_gcode_command() { // M102- extruder reverse - // M103- extruder off + // M5/M103- extruder off + case 5: case 103: #ifdef DC_EXTRUDER heater_set(DC_EXTRUDER, 0); @@ -263,12 +261,14 @@ void process_gcode_command() { temp_print(next_target.P); break; - // M106- fan on + // M7/M106- fan on #if NUM_HEATERS > 1 + case 7: case 106: heater_set(1, 255); break; // M107- fan off + case 9: case 107: heater_set(1, 0); break; From c311220c3c8da4813a8b87a4f79256ca5b282e35 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 12:06:17 +1100 Subject: [PATCH 68/82] start tool change implementation- recognise T command --- gcode_parse.c | 12 ++++++++++-- gcode_parse.h | 39 +++++++++++++++++++++++---------------- gcode_process.c | 17 +++++++++++++---- gcode_process.h | 4 ++++ 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 4222bc9..e9fc162 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -183,6 +183,11 @@ void gcode_parse_char(uint8_t c) { if (debug_flags & DEBUG_ECHO) serwrite_uint16(next_target.P); break; + case 'T': + next_target.T = read_digit.mantissa; + if (debug_flags & DEBUG_ECHO) + serwrite_uint8(next_target.T); + break; case 'N': next_target.N = decfloat_to_int(&read_digit, 1, 1); if (debug_flags & DEBUG_ECHO) @@ -244,6 +249,9 @@ void gcode_parse_char(uint8_t c) { case 'P': next_target.seen_P = 1; break; + case 'T': + next_target.seen_T = 1; + break; case 'N': next_target.seen_N = 1; break; @@ -346,8 +354,8 @@ void gcode_parse_char(uint8_t c) { // reset variables next_target.seen_X = next_target.seen_Y = next_target.seen_Z = \ next_target.seen_E = next_target.seen_F = next_target.seen_S = \ - next_target.seen_P = next_target.seen_N = next_target.seen_M = \ - next_target.seen_checksum = next_target.seen_semi_comment = \ + next_target.seen_P = next_target.seen_T = next_target.seen_N = \ + next_target.seen_M = next_target.seen_checksum = next_target.seen_semi_comment = \ next_target.seen_parens_comment = next_target.checksum_read = \ next_target.checksum_calculated = 0; last_field = 0; diff --git a/gcode_parse.h b/gcode_parse.h index 31dafb9..18e38ce 100644 --- a/gcode_parse.h +++ b/gcode_parse.h @@ -25,23 +25,28 @@ typedef struct { // this holds all the possible data from a received command typedef struct { - uint8_t seen_G :1; - uint8_t seen_M :1; - uint8_t seen_X :1; - uint8_t seen_Y :1; - uint8_t seen_Z :1; - uint8_t seen_E :1; - uint8_t seen_F :1; - uint8_t seen_S :1; + union { + struct { + uint8_t seen_G :1; + uint8_t seen_M :1; + uint8_t seen_X :1; + uint8_t seen_Y :1; + uint8_t seen_Z :1; + uint8_t seen_E :1; + uint8_t seen_F :1; + uint8_t seen_S :1; - uint8_t seen_P :1; - uint8_t seen_N :1; - uint8_t seen_checksum :1; - uint8_t seen_semi_comment :1; - uint8_t seen_parens_comment :1; - - uint8_t option_relative :1; - uint8_t option_inches :1; + uint8_t seen_P :1; + uint8_t seen_T :1; + uint8_t seen_N :1; + uint8_t seen_checksum :1; + uint8_t seen_semi_comment :1; + uint8_t seen_parens_comment :1; + uint8_t option_relative :1; + uint8_t option_inches :1; + }; + uint16_t flags; + }; uint8_t G; uint8_t M; @@ -50,6 +55,8 @@ typedef struct { int16_t S; uint16_t P; + uint8_t T; + uint32_t N; uint32_t N_expected; diff --git a/gcode_process.c b/gcode_process.c index 72451f4..e16ea55 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -75,7 +75,11 @@ void process_gcode_command() { // easier way to do this // startpoint.E = 0; // moved to dda.c, end of dda_create() and dda_queue.c, next_move() - + + if (next_target.seen_T) { + next_tool = next_target.T; + } + if (next_target.seen_G) { uint8_t axisSelected = 0; switch (next_target.G) { @@ -208,6 +212,11 @@ void process_gcode_command() { for (;;) wd_reset(); break; + + // M6- tool change + case 6: + tool = next_tool; + break; // M3/M101- extruder on case 3: case 101: @@ -412,6 +421,6 @@ void process_gcode_command() { default: sersendf_P(PSTR("E: Bad M-code %d"), next_target.M); // newline is sent from gcode_parse after we return - } - } -} + } // switch (next_target.M) + } // else if (next_target.seen_M) +} // process_gcode_command() diff --git a/gcode_process.h b/gcode_process.h index e78057d..7c453fc 100644 --- a/gcode_process.h +++ b/gcode_process.h @@ -3,6 +3,10 @@ #include "gcode_parse.h" +// the current tool +extern uint8_t tool; +// the tool to be changed when we get an M6 +extern uint8_t next_tool; void zero_x(void); void zero_y(void); From 01b5c678c6a2f10c21518fcf770d6b8242b00995 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 27 Nov 2010 12:18:27 +1100 Subject: [PATCH 69/82] minor fixes, tool variables in gcode_process and elimination of more heater code if no heaters --- gcode_process.c | 6 ++++++ heater.c | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/gcode_process.c b/gcode_process.c index e16ea55..8896871 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -17,6 +17,12 @@ #include "debug.h" #include "clock.h" +// the current tool +uint8_t tool; +// the tool to be changed when we get an M6 +uint8_t next_tool; + + /* public functions */ diff --git a/heater.c b/heater.c index 6e050ca..7d0d759 100644 --- a/heater.c +++ b/heater.c @@ -108,6 +108,7 @@ void heater_save_settings() { } void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { + #if NUM_HEATERS > 0 int16_t heater_p; int16_t heater_d; uint8_t pid_output; @@ -209,9 +210,10 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { pid_output = 0; sersendf_P(PSTR("!! heater %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter); } - #endif + #endif /* HEATER_SANITY_CHECK */ heater_set(h, pid_output); + #endif /* if NUM_HEATERS > 0 */ } void heater_set(uint8_t index, uint8_t value) { @@ -229,7 +231,7 @@ void heater_set(uint8_t index, uint8_t value) { else *(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin); } - #endif + #endif /* if NUM_HEATERS > 0 */ } void pid_set_p(uint8_t index, int32_t p) { From 6e7099e9c98abc0837296e18797309440a9a731c Mon Sep 17 00:00:00 2001 From: Casainho Date: Thu, 2 Dec 2010 11:39:47 +1100 Subject: [PATCH 70/82] missing break in sersendf.c Signed-off-by: Michael Moon --- sersendf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sersendf.c b/sersendf.c index 13d4eae..7d6666f 100644 --- a/sersendf.c +++ b/sersendf.c @@ -19,6 +19,7 @@ void sersendf(char *format, ...) { switch(c) { case 'l': j = 4; + break; case 'u': if (j == 4) serwrite_uint32(va_arg(args, uint32_t)); From 452baed484f80736e659e5a80bc33efcfea2e9d3 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 4 Dec 2010 11:35:14 +1100 Subject: [PATCH 71/82] change temporal counters to count down instead of up --- dda.c | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/dda.c b/dda.c index ca93e39..3e97eee 100644 --- a/dda.c +++ b/dda.c @@ -288,15 +288,10 @@ void dda_create(DDA *dda, TARGET *target) { dda->n = 1; dda->ramp_state = RAMP_UP; #elif defined ACCELERATION_TEMPORAL - dda->x_step_interval = move_duration / dda->x_delta; - dda->y_step_interval = move_duration / dda->y_delta; - dda->z_step_interval = move_duration / dda->z_delta; - dda->e_step_interval = move_duration / dda->e_delta; - - dda->x_counter = 0; - dda->y_counter = 0; - dda->z_counter = 0; - dda->e_counter = 0; + dda->x_counter = dda->x_step_interval = move_duration / dda->x_delta; + dda->y_counter = dda->y_step_interval = move_duration / dda->y_delta; + dda->z_counter = dda->z_step_interval = move_duration / dda->z_delta; + dda->e_counter = dda->e_step_interval = move_duration / dda->e_delta; dda->c = dda->x_step_interval; if (dda->y_step_interval < dda->c) @@ -379,7 +374,7 @@ void dda_step(DDA *dda) { uint8_t did_step = 0; #ifdef ACCELERATION_TEMPORAL - if (dda->x_counter > dda->x_step_interval) { + if (dda->x_counter <= 0) { if ((current_position.X != dda->endpoint.X) /* && (x_max() != dda->x_direction) && (x_min() == dda->x_direction) */) { x_step(); @@ -388,10 +383,10 @@ void dda_step(DDA *dda) { else current_position.X--; } - dda->x_counter -= dda->x_step_interval; + dda->x_counter += dda->x_step_interval; dda->x_delta--; } - if (dda->y_counter > dda->y_step_interval) { + if (dda->y_counter <= 0) { if ((current_position.Y != dda->endpoint.Y) /* && (y_max() != dda->y_direction) && (y_min() == dda->y_direction) */) { y_step(); @@ -400,10 +395,10 @@ void dda_step(DDA *dda) { else current_position.Y--; } - dda->y_counter -= dda->y_step_interval; + dda->y_counter += dda->y_step_interval; dda->y_delta--; } - if (dda->z_counter > dda->z_step_interval) { + if (dda->z_counter <= 0) { if ((current_position.Z != dda->endpoint.Z) /* && (z_max() != dda->z_direction) && (z_min() == dda->z_direction) */) { z_step(); @@ -412,10 +407,10 @@ void dda_step(DDA *dda) { else current_position.Z--; } - dda->z_counter -= dda->z_step_interval; + dda->z_counter += dda->z_step_interval; dda->z_delta--; } - if (dda->e_counter > dda->e_step_interval) { + if (dda->e_counter <= 0) { if ((current_position.E != dda->endpoint.E) /* && (e_max() != dda->e_direction) && (e_min() == dda->e_direction) */) { e_step(); @@ -424,7 +419,7 @@ void dda_step(DDA *dda) { else current_position.E--; } - dda->e_counter -= dda->e_step_interval; + dda->e_counter += dda->e_step_interval; dda->e_delta--; } #else @@ -542,22 +537,22 @@ void dda_step(DDA *dda) { dda->step_no++; #endif #ifdef ACCELERATION_TEMPORAL - dda->c = dda->x_step_interval - dda->x_counter; - if ((dda->y_step_interval - dda->y_counter) < dda->c) - dda->c = dda->y_step_interval - dda->y_counter; - if ((dda->z_step_interval - dda->z_counter) < dda->c) - dda->c = dda->z_step_interval - dda->z_counter; - if ((dda->e_step_interval - dda->e_counter) < dda->c) - dda->c = dda->e_step_interval - dda->e_counter; + dda->c = dda->x_counter; + if (dda->y_counter < dda->c) + dda->c = dda->y_counter; + if (dda->z_counter < dda->c) + dda->c = dda->z_counter; + if (dda->e_counter < dda->c) + dda->c = dda->e_counter; if (dda->x_delta) - dda->x_counter += dda->c; + dda->x_counter -= dda->c; if (dda->y_delta) - dda->y_counter += dda->c; + dda->y_counter -= dda->c; if (dda->z_delta) - dda->z_counter += dda->c; + dda->z_counter -= dda->c; if (dda->e_delta) - dda->e_counter += dda->c; + dda->e_counter -= dda->c; if ( (dda->x_delta > 0) || (dda->y_delta > 0) || From 1f30c7f43b0279b28fb30a53b4987fcbe2bcbb76 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 6 Dec 2010 20:34:21 +1100 Subject: [PATCH 72/82] bug in M115, fixed --- gcode_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcode_process.c b/gcode_process.c index 8896871..9b8c644 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -326,7 +326,7 @@ void process_gcode_command() { break; // M115- capabilities string case 115: - sersendf_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d"), 1, NUM_TEMP_SENSORS, NUM_HEATERS); + sersendf_P(PSTR("FIRMWARE_NAME:FiveD_on_Arduino FIRMWARE_URL:http%%3A//github.com/triffid/FiveD_on_Arduino/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d"), 1, NUM_TEMP_SENSORS, NUM_HEATERS); // newline is sent from gcode_parse after we return break; From eaddc510b4668adb912f6f8c8fbb69f7ca0c24cb Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Tue, 7 Dec 2010 15:16:25 +1100 Subject: [PATCH 73/82] no longer assume analog port is port C, as this assumption is false --- analog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analog.c b/analog.c index 2cf3e00..e4aebbb 100644 --- a/analog.c +++ b/analog.c @@ -54,7 +54,7 @@ void analog_init() { adc_counter = 0; adc_running_mask = 1; - DDRC &= ANALOG_MASK; + AIO0_DDR &= ANALOG_MASK; DIDR0 = ANALOG_MASK & 0x3F; // now we start the first conversion and leave the rest to the interrupt From 5dfd76a718e2fc07fee128c9451dad2908fa7ea4 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sat, 11 Dec 2010 17:06:58 +1100 Subject: [PATCH 74/82] be more strict about sersendf format strings, revert to raw send if invalid char found --- sersendf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sersendf.c b/sersendf.c index 7d6666f..4145fe7 100644 --- a/sersendf.c +++ b/sersendf.c @@ -52,6 +52,7 @@ void sersendf(char *format, ...) { j = 0; break; default: + serial_writechar(c); j = 0; break; } @@ -112,10 +113,11 @@ void sersendf_P(PGM_P format, ...) { j = 0; break; case 'p': - serwrite_hex16(va_arg(args, uint16_t)); + serwrite_hex16(va_arg(args, uint16_t));*/ default: + serial_writechar(c); j = 0; - break;*/ + break; } } else { From eaf8a9dcecd1facd5cb6c31af076a2385498faba Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 13 Dec 2010 20:09:04 +1100 Subject: [PATCH 75/82] replace symlinks with hardlinks because windows is stupid, will make future commits look messier than necessary --- extruder/analog.c | 104 +++++++++++- extruder/analog.h | 32 +++- extruder/arduino.h | 65 +++++++- extruder/arduino_168_328p.h | 227 +++++++++++++++++++++++++- extruder/debug.h | 22 ++- extruder/delay.c | 51 +++++- extruder/delay.h | 16 +- extruder/heater.c | 252 ++++++++++++++++++++++++++++- extruder/heater.h | 21 ++- extruder/temp.c | 276 ++++++++++++++++++++++++++++++- extruder/temp.h | 30 +++- extruder/watchdog.c | 48 +++++- extruder/watchdog.h | 23 ++- intercom.c | 220 ++++++++++++++++++++++++- intercom.h | 18 ++- mendel_cmd | 313 +++++++++++++++++++++++++++++++++++- 16 files changed, 1702 insertions(+), 16 deletions(-) mode change 120000 => 100644 extruder/analog.c mode change 120000 => 100644 extruder/analog.h mode change 120000 => 100644 extruder/arduino.h mode change 120000 => 100644 extruder/arduino_168_328p.h mode change 120000 => 100644 extruder/debug.h mode change 120000 => 100644 extruder/delay.c mode change 120000 => 100644 extruder/delay.h mode change 120000 => 100644 extruder/heater.c mode change 120000 => 100644 extruder/heater.h mode change 120000 => 100644 extruder/temp.c mode change 120000 => 100644 extruder/temp.h mode change 120000 => 100644 extruder/watchdog.c mode change 120000 => 100644 extruder/watchdog.h mode change 120000 => 100644 intercom.c mode change 120000 => 100644 intercom.h mode change 120000 => 100755 mendel_cmd diff --git a/extruder/analog.c b/extruder/analog.c deleted file mode 120000 index 4ba410b..0000000 --- a/extruder/analog.c +++ /dev/null @@ -1 +0,0 @@ -../analog.c \ No newline at end of file diff --git a/extruder/analog.c b/extruder/analog.c new file mode 100644 index 0000000..e4aebbb --- /dev/null +++ b/extruder/analog.c @@ -0,0 +1,103 @@ +#include "analog.h" + +#include + +#ifndef ANALOG_MASK + #warning ANALOG_MASK not defined - analog subsystem disabled + #define ANALOG_MASK 0 +#endif + +uint8_t adc_running_mask, adc_counter; + +#if ANALOG_MASK & 2 + #define ANALOG_START 1 + #define ANALOG_START_MASK 2 +#elif ANALOG_MASK & 4 + #define ANALOG_START 2 + #define ANALOG_START_MASK 4 +#elif ANALOG_MASK & 8 + #define ANALOG_START 3 + #define ANALOG_START_MASK 8 +#elif ANALOG_MASK & 16 + #define ANALOG_START 4 + #define ANALOG_START_MASK 16 +#elif ANALOG_MASK & 32 + #define ANALOG_START 5 + #define ANALOG_START_MASK 32 +#elif ANALOG_MASK & 64 + #define ANALOG_START 6 + #define ANALOG_START_MASK 64 +#elif ANALOG_MASK & 128 + #define ANALOG_START 7 + #define ANALOG_START_MASK 128 +#else + // ANALOG_MASK == 1 or 0, either way defines are the same except they're not used if ANALOG_MASK == 0 + #define ANALOG_START 0 + #define ANALOG_START_MASK 1 +#endif + +volatile uint16_t adc_result[8] __attribute__ ((__section__ (".bss"))); + +void analog_init() { + #if ANALOG_MASK > 0 + #ifdef PRR + PRR &= ~MASK(PRADC); + #elif defined PRR0 + PRR0 &= ~MASK(PRADC); + #endif + + ADMUX = REFERENCE; + + // ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz. + ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0); + + adc_counter = 0; + adc_running_mask = 1; + + AIO0_DDR &= ANALOG_MASK; + DIDR0 = ANALOG_MASK & 0x3F; + + // now we start the first conversion and leave the rest to the interrupt + ADCSRA |= MASK(ADIE) | MASK(ADSC); + #endif /* ANALOG_MASK > 0 */ +} + +ISR(ADC_vect, ISR_NOBLOCK) { + // emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts + adc_result[ADMUX & 0x0F] = ADC; + // find next channel + do { + adc_counter++; + adc_running_mask <<= 1; + if (adc_counter == 8) { + adc_counter = ANALOG_START; + adc_running_mask = ANALOG_START_MASK; + } + } while ((adc_running_mask & ANALOG_MASK) == 0); + + // start next conversion + ADMUX = (adc_counter) | REFERENCE; + ADCSRA |= MASK(ADSC); +} + +uint16_t analog_read(uint8_t channel) { + #if ANALOG_MASK > 0 + uint16_t r; + + uint8_t sreg; + // save interrupt flag + sreg = SREG; + // disable interrupts + cli(); + + // atomic 16-bit copy + r = adc_result[channel]; + + // restore interrupt flag + SREG = sreg; + + return r; + #else + return 0; + #endif +} diff --git a/extruder/analog.h b/extruder/analog.h deleted file mode 120000 index 882b768..0000000 --- a/extruder/analog.h +++ /dev/null @@ -1 +0,0 @@ -../analog.h \ No newline at end of file diff --git a/extruder/analog.h b/extruder/analog.h new file mode 100644 index 0000000..21ab830 --- /dev/null +++ b/extruder/analog.h @@ -0,0 +1,31 @@ +#ifndef _ANALOG_H +#define _ANALOG_H + +#include + +#define REFERENCE_AREF 0 +#define REFERENCE_AVCC 64 +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) + #define REFERENCE_1V1 192 +#elif defined (__AVR_ATmega_644__) || defined (__AVR_ATmega644p__) + #define REFERENCE_1V1 128 + #define REFERENCE_2V56 192 +#endif + +#include "config.h" + +#ifndef REFERENCE +#warning define REFERENCE as one of +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) + #warning REFERENCE_AREF, REFERENCE_AVCC or REFERENCE_1V1 +#elif defined (__AVR_ATmega_644__) || defined (__AVR_ATmega644p__) + #warning REFERENCE_AREF, REFERENCE_AVCC, REFERENCE_1V1 or REFERENCE_2V56 +#endif +#warning in your config.h +#error REFERENCE undefined +#endif + +void analog_init(void); +uint16_t analog_read(uint8_t channel); + +#endif /* _ANALOG_H */ diff --git a/extruder/arduino.h b/extruder/arduino.h deleted file mode 120000 index 14df5af..0000000 --- a/extruder/arduino.h +++ /dev/null @@ -1 +0,0 @@ -../arduino.h \ No newline at end of file diff --git a/extruder/arduino.h b/extruder/arduino.h new file mode 100644 index 0000000..476ba1b --- /dev/null +++ b/extruder/arduino.h @@ -0,0 +1,64 @@ +#ifndef _ARDUINO_H +#define _ARDUINO_H + +#include + +/* + utility functions +*/ + +#ifndef MASK +#define MASK(PIN) (1 << PIN) +#endif + +/* + magic I/O routines + + now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0); +*/ + +#define _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN)) +#define _WRITE(IO, v) do { if (v) { IO ## _WPORT |= MASK(IO ## _PIN); } else { IO ## _WPORT &= ~MASK(IO ## _PIN); }; } while (0) +#define _TOGGLE(IO) do { IO ## _RPORT = MASK(IO ## _PIN); } while (0) + +#define _SET_INPUT(IO) do { IO ## _DDR &= ~MASK(IO ## _PIN); } while (0) +#define _SET_OUTPUT(IO) do { IO ## _DDR |= MASK(IO ## _PIN); } while (0) + +#define _GET_INPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) == 0) +#define _GET_OUTPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) != 0) + +// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html + +#define READ(IO) _READ(IO) +#define WRITE(IO, v) _WRITE(IO, v) +#define TOGGLE(IO) _TOGGLE(IO) + +#define SET_INPUT(IO) _SET_INPUT(IO) +#define SET_OUTPUT(IO) _SET_OUTPUT(IO) + +#define GET_INPUT(IO) _GET_INPUT(IO) +#define GET_OUTPUT(IO) _GET_OUTPUT(IO) + +/* + ports and functions + + added as necessary or if I feel like it- not a comprehensive list! +*/ + +#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) + #include "arduino_168_328p.h" +#endif /* _AVR_ATmega{168,328,328P}__ */ + +#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) + #include "arduino_644.h" +#endif /* _AVR_ATmega{644,644P,644PA}__ */ + +#if defined (__AVR_ATmega1280__) + #include "arduino_1280.h" +#endif /* __AVR_ATmega1280__ */ + +#ifndef DIO0_PIN +#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please tell us via the forum thread +#endif + +#endif /* _ARDUINO_H */ diff --git a/extruder/arduino_168_328p.h b/extruder/arduino_168_328p.h deleted file mode 120000 index 3940ca5..0000000 --- a/extruder/arduino_168_328p.h +++ /dev/null @@ -1 +0,0 @@ -../arduino_168_328p.h \ No newline at end of file diff --git a/extruder/arduino_168_328p.h b/extruder/arduino_168_328p.h new file mode 100644 index 0000000..9bc289b --- /dev/null +++ b/extruder/arduino_168_328p.h @@ -0,0 +1,226 @@ +// UART +#define RXD DIO0 +#define TXD DIO1 + +// SPI +#define SCK DIO13 +#define MISO DIO12 +#define MOSI DIO11 +#define SS DIO10 + +// TWI (I2C) +#define SCL AIO5 +#define SDA AIO4 + +// timers and PWM +#define OC0A DIO6 +#define OC0B DIO5 +#define OC1A DIO9 +#define OC1B DIO10 +#define OC2A DIO11 +#define OC2B DIO3 + +#define DEBUG_LED AIO5 + +/* +pins +*/ + +#define DIO0_PIN PIND0 +#define DIO0_RPORT PIND +#define DIO0_WPORT PORTD +#define DIO0_DDR DDRD + +#define DIO1_PIN PIND1 +#define DIO1_RPORT PIND +#define DIO1_WPORT PORTD +#define DIO1_DDR DDRD + +#define DIO2_PIN PIND2 +#define DIO2_RPORT PIND +#define DIO2_WPORT PORTD +#define DIO2_DDR DDRD + +#define DIO3_PIN PIND3 +#define DIO3_RPORT PIND +#define DIO3_WPORT PORTD +#define DIO3_DDR DDRD + +#define DIO4_PIN PIND4 +#define DIO4_RPORT PIND +#define DIO4_WPORT PORTD +#define DIO4_DDR DDRD + +#define DIO5_PIN PIND5 +#define DIO5_RPORT PIND +#define DIO5_WPORT PORTD +#define DIO5_DDR DDRD + +#define DIO6_PIN PIND6 +#define DIO6_RPORT PIND +#define DIO6_WPORT PORTD +#define DIO6_DDR DDRD + +#define DIO7_PIN PIND7 +#define DIO7_RPORT PIND +#define DIO7_WPORT PORTD +#define DIO7_DDR DDRD + +#define DIO8_PIN PINB0 +#define DIO8_RPORT PINB +#define DIO8_WPORT PORTB +#define DIO8_DDR DDRB + +#define DIO9_PIN PINB1 +#define DIO9_RPORT PINB +#define DIO9_WPORT PORTB +#define DIO9_DDR DDRB + +#define DIO10_PIN PINB2 +#define DIO10_RPORT PINB +#define DIO10_WPORT PORTB +#define DIO10_DDR DDRB + +#define DIO11_PIN PINB3 +#define DIO11_RPORT PINB +#define DIO11_WPORT PORTB +#define DIO11_DDR DDRB + +#define DIO12_PIN PINB4 +#define DIO12_RPORT PINB +#define DIO12_WPORT PORTB +#define DIO12_DDR DDRB + +#define DIO13_PIN PINB5 +#define DIO13_RPORT PINB +#define DIO13_WPORT PORTB +#define DIO13_DDR DDRB + +#define AIO0_PIN PINC0 +#define AIO0_RPORT PINC +#define AIO0_WPORT PORTC +#define AIO0_DDR DDRC + +#define AIO1_PIN PINC1 +#define AIO1_RPORT PINC +#define AIO1_WPORT PORTC +#define AIO1_DDR DDRC + +#define AIO2_PIN PINC2 +#define AIO2_RPORT PINC +#define AIO2_WPORT PORTC +#define AIO2_DDR DDRC + +#define AIO3_PIN PINC3 +#define AIO3_RPORT PINC +#define AIO3_WPORT PORTC +#define AIO3_DDR DDRC + +#define AIO4_PIN PINC4 +#define AIO4_RPORT PINC +#define AIO4_WPORT PORTC +#define AIO4_DDR DDRC + +#define AIO5_PIN PINC5 +#define AIO5_RPORT PINC +#define AIO5_WPORT PORTC +#define AIO5_DDR DDRC + +#define PB0_PIN PINB0 +#define PB0_RPORT PINB +#define PB0_WPORT PORTB +#define PB0_DDR DDRB +#define PB1_PIN PINB1 +#define PB1_RPORT PINB +#define PB1_WPORT PORTB +#define PB1_DDR DDRB +#define PB2_PIN PINB2 +#define PB2_RPORT PINB +#define PB2_WPORT PORTB +#define PB2_DDR DDRB +#define PB3_PIN PINB3 +#define PB3_RPORT PINB +#define PB3_WPORT PORTB +#define PB3_DDR DDRB +#define PB4_PIN PINB4 +#define PB4_RPORT PINB +#define PB4_WPORT PORTB +#define PB4_DDR DDRB +#define PB5_PIN PINB5 +#define PB5_RPORT PINB +#define PB5_WPORT PORTB +#define PB5_DDR DDRB +#define PB6_PIN PINB6 +#define PB6_RPORT PINB +#define PB6_WPORT PORTB +#define PB6_DDR DDRB +#define PB7_PIN PINB7 +#define PB7_RPORT PINB +#define PB7_WPORT PORTB +#define PB7_DDR DDRB + +#define PC0_PIN PINC0 +#define PC0_RPORT PINC +#define PC0_WPORT PORTC +#define PC0_DDR DDRC +#define PC1_PIN PINC1 +#define PC1_RPORT PINC +#define PC1_WPORT PORTC +#define PC1_DDR DDRC +#define PC2_PIN PINC2 +#define PC2_RPORT PINC +#define PC2_WPORT PORTC +#define PC2_DDR DDRC +#define PC3_PIN PINC3 +#define PC3_RPORT PINC +#define PC3_WPORT PORTC +#define PC3_DDR DDRC +#define PC4_PIN PINC4 +#define PC4_RPORT PINC +#define PC4_WPORT PORTC +#define PC4_DDR DDRC +#define PC5_PIN PINC5 +#define PC5_RPORT PINC +#define PC5_WPORT PORTC +#define PC5_DDR DDRC +#define PC6_PIN PINC6 +#define PC6_RPORT PINC +#define PC6_WPORT PORTC +#define PC6_DDR DDRC +#define PC7_PIN PINC7 +#define PC7_RPORT PINC +#define PC7_WPORT PORTC +#define PC7_DDR DDRC + +#define PD0_PIN PIND0 +#define PD0_RPORT PIND +#define PD0_WPORT PORTD +#define PD0_DDR DDRD +#define PD1_PIN PIND1 +#define PD1_RPORT PIND +#define PD1_WPORT PORTD +#define PD1_DDR DDRD +#define PD2_PIN PIND2 +#define PD2_RPORT PIND +#define PD2_WPORT PORTD +#define PD2_DDR DDRD +#define PD3_PIN PIND3 +#define PD3_RPORT PIND +#define PD3_WPORT PORTD +#define PD3_DDR DDRD +#define PD4_PIN PIND4 +#define PD4_RPORT PIND +#define PD4_WPORT PORTD +#define PD4_DDR DDRD +#define PD5_PIN PIND5 +#define PD5_RPORT PIND +#define PD5_WPORT PORTD +#define PD5_DDR DDRD +#define PD6_PIN PIND6 +#define PD6_RPORT PIND +#define PD6_WPORT PORTD +#define PD6_DDR DDRD +#define PD7_PIN PIND7 +#define PD7_RPORT PIND +#define PD7_WPORT PORTD +#define PD7_DDR DDRD diff --git a/extruder/debug.h b/extruder/debug.h deleted file mode 120000 index 845c7cc..0000000 --- a/extruder/debug.h +++ /dev/null @@ -1 +0,0 @@ -../debug.h \ No newline at end of file diff --git a/extruder/debug.h b/extruder/debug.h new file mode 100644 index 0000000..e96e268 --- /dev/null +++ b/extruder/debug.h @@ -0,0 +1,21 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#include + +#ifdef DEBUG + #define DEBUG_PID 1 + #define DEBUG_DDA 2 + #define DEBUG_POSITION 4 +#else + // by setting these to zero, the compiler should optimise the relevant code out + #define DEBUG_PID 0 + #define DEBUG_DDA 0 + #define DEBUG_POSITION 0 +#endif + +#define DEBUG_ECHO 128 + +extern volatile uint8_t debug_flags; + +#endif /* _DEBUG_H */ diff --git a/extruder/delay.c b/extruder/delay.c deleted file mode 120000 index 1df3093..0000000 --- a/extruder/delay.c +++ /dev/null @@ -1 +0,0 @@ -../delay.c \ No newline at end of file diff --git a/extruder/delay.c b/extruder/delay.c new file mode 100644 index 0000000..fb3e2bb --- /dev/null +++ b/extruder/delay.c @@ -0,0 +1,50 @@ +#include "delay.h" + +#include "watchdog.h" + +// delay( microseconds ) +void delay(uint32_t delay) { + wd_reset(); + while (delay > 65535) { + delayMicrosecondsInterruptible(65533); + delay -= 65535; + wd_reset(); + } + delayMicrosecondsInterruptible(delay & 0xFFFF); + wd_reset(); +} + +// delay_ms( milliseconds ) +void delay_ms(uint32_t delay) { + wd_reset(); + while (delay > 65) { + delayMicrosecondsInterruptible(64999); + delay -= 65; + wd_reset(); + } + delayMicrosecondsInterruptible(delay * 1000); + wd_reset(); +} + +void delayMicrosecondsInterruptible(uint16_t us) +{ + // for a one-microsecond delay, simply return. the overhead + // of the function call yields a delay of approximately 1 1/8 us. + if (--us == 0) + return; + + // the following loop takes a quarter of a microsecond (4 cycles) + // per iteration, so execute it four times for each microsecond of + // delay requested. + us <<= 2; + + // account for the time taken in the preceeding commands. + us -= 2; + + // busy wait + __asm__ __volatile__ ("1: sbiw %0,1" "\n\t" // 2 cycles + "brne 1b" : + "=w" (us) : + "0" (us) // 2 cycles + ); +} diff --git a/extruder/delay.h b/extruder/delay.h deleted file mode 120000 index 8c2af90..0000000 --- a/extruder/delay.h +++ /dev/null @@ -1 +0,0 @@ -../delay.h \ No newline at end of file diff --git a/extruder/delay.h b/extruder/delay.h new file mode 100644 index 0000000..83aaf36 --- /dev/null +++ b/extruder/delay.h @@ -0,0 +1,15 @@ +#ifndef _DELAY_H +#define _DELAY_H + +#include + +#define WAITING_DELAY 10 MS + +void delay(uint32_t delay); + +void delay_ms(uint32_t delay); + +#define delay_us(d) delayMicrosecondsInterruptible(d) +void delayMicrosecondsInterruptible(unsigned int us); + +#endif /* _DELAY_H */ diff --git a/extruder/heater.c b/extruder/heater.c deleted file mode 120000 index acfa7db..0000000 --- a/extruder/heater.c +++ /dev/null @@ -1 +0,0 @@ -../heater.c \ No newline at end of file diff --git a/extruder/heater.c b/extruder/heater.c new file mode 100644 index 0000000..7d0d759 --- /dev/null +++ b/extruder/heater.c @@ -0,0 +1,251 @@ +#include "heater.h" + +#include +#include +#include + +#include "arduino.h" +#include "debug.h" +#ifndef EXTRUDER +#include "sersendf.h" +#endif + +#define HEATER_C +#include "config.h" + +// this struct holds the heater PID factors that are stored in the EEPROM during poweroff +struct { + int32_t p_factor; + int32_t i_factor; + int32_t d_factor; + int16_t i_limit; +} heaters_pid[NUM_HEATERS]; + +// this struct holds the runtime heater data- PID integrator history, temperature history, sanity checker +struct { + int16_t heater_i; + + uint16_t temp_history[TH_COUNT]; + uint8_t temp_history_pointer; + + #ifdef HEATER_SANITY_CHECK + uint16_t sanity_counter; + uint16_t sane_temperature; + #endif +} heaters_runtime[NUM_HEATERS]; + +#define DEFAULT_P 8192 +#define DEFAULT_I 512 +#define DEFAULT_D 24576 +#define DEFAULT_I_LIMIT 384 + +// this lives in the eeprom so we can save our PID settings for each heater +typedef struct { + int32_t EE_p_factor; + int32_t EE_i_factor; + int32_t EE_d_factor; + int16_t EE_i_limit; +} EE_factor; + +EE_factor EEMEM EE_factors[NUM_HEATERS]; + +void heater_init() { + #if NUM_HEATERS > 0 + uint8_t i; + // setup pins + for (i = 0; i < NUM_HEATERS; i++) { + *(heaters[i].heater_port) &= ~MASK(heaters[i].heater_pin); + // DDR is always 1 address below PORT. ugly code but saves ram and an extra field in heaters[] which will never be used anywhere but here + *(heaters[i].heater_port - 1) |= MASK(heaters[i].heater_pin); + if (heaters[i].heater_pwm) { + *heaters[i].heater_pwm = 0; + // this is somewhat ugly too, but switch() won't accept pointers for reasons unknown + switch((uint16_t) heaters[i].heater_pwm) { + case (uint16_t) &OCR0A: + TCCR0A |= MASK(COM0A1); + break; + case (uint16_t) &OCR0B: + TCCR0A |= MASK(COM0B1); + break; + case (uint16_t) &OCR2A: + TCCR2A |= MASK(COM2A1); + break; + case (uint16_t) &OCR2B: + TCCR2A |= MASK(COM2B1); + break; + } + } + + #ifdef HEATER_SANITY_CHECK + // 0 is a "sane" temperature when we're trying to cool down + heaters_runtime[i].sane_temperature = 0; + #endif + + // read factors from eeprom + heaters_pid[i].p_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_p_factor); + heaters_pid[i].i_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_i_factor); + heaters_pid[i].d_factor = eeprom_read_dword((uint32_t *) &EE_factors[i].EE_d_factor); + heaters_pid[i].i_limit = eeprom_read_word((uint16_t *) &EE_factors[i].EE_i_limit); + + if ((heaters_pid[i].p_factor == 0) && (heaters_pid[i].i_factor == 0) && (heaters_pid[i].d_factor == 0) && (heaters_pid[i].i_limit == 0)) { + heaters_pid[i].p_factor = DEFAULT_P; + heaters_pid[i].i_factor = DEFAULT_I; + heaters_pid[i].d_factor = DEFAULT_D; + heaters_pid[i].i_limit = DEFAULT_I_LIMIT; + } + } + #endif +} + +void heater_save_settings() { + uint8_t i; + for (i = 0; i < NUM_HEATERS; i++) { + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_p_factor, heaters_pid[i].p_factor); + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_i_factor, heaters_pid[i].i_factor); + eeprom_write_dword((uint32_t *) &EE_factors[i].EE_d_factor, heaters_pid[i].d_factor); + eeprom_write_word((uint16_t *) &EE_factors[i].EE_i_limit, heaters_pid[i].i_limit); + } +} + +void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { + #if NUM_HEATERS > 0 + int16_t heater_p; + int16_t heater_d; + uint8_t pid_output; + + int16_t t_error = target_temp - current_temp; + + heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer++] = current_temp; + heaters_runtime[h].temp_history_pointer &= (TH_COUNT - 1); + + // PID stuff + // proportional + heater_p = t_error; + + // integral + heaters_runtime[h].heater_i += t_error; + // prevent integrator wind-up + if (heaters_runtime[h].heater_i > heaters_pid[h].i_limit) + heaters_runtime[h].heater_i = heaters_pid[h].i_limit; + else if (heaters_runtime[h].heater_i < -heaters_pid[h].i_limit) + heaters_runtime[h].heater_i = -heaters_pid[h].i_limit; + + // derivative + // note: D follows temp rather than error so there's no large derivative when the target changes + heater_d = heaters_runtime[h].temp_history[heaters_runtime[h].temp_history_pointer] - current_temp; + + // combine factors + int32_t pid_output_intermed = ( + ( + (((int32_t) heater_p) * heaters_pid[h].p_factor) + + (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + + (((int32_t) heater_d) * heaters_pid[h].d_factor) + ) / PID_SCALE + ); + + // rebase and limit factors + if (pid_output_intermed > 255) + pid_output = 255; + else if (pid_output_intermed < 0) + pid_output = 0; + else + pid_output = pid_output_intermed & 0xFF; + + #ifdef DEBUG + if (debug_flags & DEBUG_PID) + sersendf_P(PSTR("T{E:%d, P:%d * %ld = %ld / I:%d * %ld = %ld / D:%d * %ld = %ld # O: %ld = %u}\n"), t_error, heater_p, heaters_pid[h].p_factor, (int32_t) heater_p * heaters_pid[h].p_factor / PID_SCALE, heaters_runtime[h].heater_i, heaters_pid[h].i_factor, (int32_t) heaters_runtime[h].heater_i * heaters_pid[h].i_factor / PID_SCALE, heater_d, heaters_pid[h].d_factor, (int32_t) heater_d * heaters_pid[h].d_factor / PID_SCALE, pid_output_intermed, pid_output); + #endif + + #ifdef HEATER_SANITY_CHECK + // check heater sanity + // implementation is a moving window with some slow-down to compensate for thermal mass + if (target_temp > (current_temp + TEMP_HYSTERESIS)) { + // heating + if (current_temp > heaters_runtime[h].sane_temperature) + // hotter than sane- good since we're heating unless too hot + heaters_runtime[h].sane_temperature = current_temp; + else { + if (heaters_runtime[h].sanity_counter < 40) + heaters_runtime[h].sanity_counter++; + else { + heaters_runtime[h].sanity_counter = 0; + // ratchet up expected temp + heaters_runtime[h].sane_temperature++; + } + } + // limit to target, so if we overshoot by too much for too long an error is flagged + if (heaters_runtime[h].sane_temperature > target_temp) + heaters_runtime[h].sane_temperature = target_temp; + } + else if (target_temp < (current_temp - TEMP_HYSTERESIS)) { + // cooling + if (current_temp < heaters_runtime[h].sane_temperature) + // cooler than sane- good since we're cooling + heaters_runtime[h].sane_temperature = current_temp; + else { + if (heaters_runtime[h].sanity_counter < 125) + heaters_runtime[h].sanity_counter++; + else { + heaters_runtime[h].sanity_counter = 0; + // ratchet down expected temp + heaters_runtime[h].sane_temperature--; + } + } + // if we're at or below 60 celsius, don't freak out if we can't drop any more. + if (current_temp <= 240) + heaters_runtime[h].sane_temperature = current_temp; + // limit to target, so if we don't cool down for too long an error is flagged + else if (heaters_runtime[h].sane_temperature < target_temp) + heaters_runtime[h].sane_temperature = target_temp; + } + // we're within HYSTERESIS of our target + else { + heaters_runtime[h].sane_temperature = current_temp; + heaters_runtime[h].sanity_counter = 0; + } + + // compare where we're at to where we should be + if (labs(current_temp - heaters_runtime[h].sane_temperature) > TEMP_HYSTERESIS) { + // no change, or change in wrong direction for a long time- heater is broken! + pid_output = 0; + sersendf_P(PSTR("!! heater %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter); + } + #endif /* HEATER_SANITY_CHECK */ + + heater_set(h, pid_output); + #endif /* if NUM_HEATERS > 0 */ +} + +void heater_set(uint8_t index, uint8_t value) { + #if NUM_HEATERS > 0 + if (heaters[index].heater_pwm) { + *(heaters[index].heater_pwm) = value; + #ifdef DEBUG + if (debug_flags & DEBUG_PID) + sersendf_P(PSTR("PWM{%u = %u}\n"), index, OCR0A); + #endif + } + else { + if (value >= 8) + *(heaters[index].heater_port) |= MASK(heaters[index].heater_pin); + else + *(heaters[index].heater_port) &= ~MASK(heaters[index].heater_pin); + } + #endif /* if NUM_HEATERS > 0 */ +} + +void pid_set_p(uint8_t index, int32_t p) { + heaters_pid[index].p_factor = p; +} + +void pid_set_i(uint8_t index, int32_t i) { + heaters_pid[index].i_factor = i; +} + +void pid_set_d(uint8_t index, int32_t d) { + heaters_pid[index].d_factor = d; +} + +void pid_set_i_limit(uint8_t index, int32_t i_limit) { + heaters_pid[index].i_limit = i_limit; +} diff --git a/extruder/heater.h b/extruder/heater.h deleted file mode 120000 index 22c6069..0000000 --- a/extruder/heater.h +++ /dev/null @@ -1 +0,0 @@ -../heater.h \ No newline at end of file diff --git a/extruder/heater.h b/extruder/heater.h new file mode 100644 index 0000000..fdc9dc9 --- /dev/null +++ b/extruder/heater.h @@ -0,0 +1,20 @@ +#ifndef _HEATER_H +#define _HEATER_H + +#include + +#define enable_heater() heater_set(0, 64) +#define disable_heater() heater_set(0, 0) + +void heater_init(void); +void heater_save_settings(void); + +void heater_set(uint8_t index, uint8_t value); +void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp); + +void pid_set_p(uint8_t index, int32_t p); +void pid_set_i(uint8_t index, int32_t i); +void pid_set_d(uint8_t index, int32_t d); +void pid_set_i_limit(uint8_t index, int32_t i_limit); + +#endif /* _HEATER_H */ diff --git a/extruder/temp.c b/extruder/temp.c deleted file mode 120000 index f59d719..0000000 --- a/extruder/temp.c +++ /dev/null @@ -1 +0,0 @@ -../temp.c \ No newline at end of file diff --git a/extruder/temp.c b/extruder/temp.c new file mode 100644 index 0000000..4809218 --- /dev/null +++ b/extruder/temp.c @@ -0,0 +1,275 @@ +#include "temp.h" + +#include +#include +#include + +typedef enum { + TT_THERMISTOR, + TT_MAX6675, + TT_AD595, + TT_PT100, + TT_INTERCOM +} temp_types; + +typedef enum { + PRESENT, + TCOPEN +} temp_flags_enum; + +#define TEMP_C +#include "config.h" + +#include "arduino.h" +#include "delay.h" +#include "debug.h" +#ifndef EXTRUDER + #include "sersendf.h" +#endif +#include "heater.h" +#ifdef GEN3 + #include "intercom.h" +#endif + +// this struct holds the runtime sensor data- read temperatures, targets, etc +struct { + temp_flags_enum temp_flags; + + uint16_t last_read_temp; + uint16_t target_temp; + + uint8_t temp_residency; + + uint16_t next_read_time; +} temp_sensors_runtime[NUM_TEMP_SENSORS]; + +#ifdef TEMP_MAX6675 +#endif + +#ifdef TEMP_THERMISTOR +#include "analog.h" + +#define NUMTEMPS 20 +uint16_t temptable[NUMTEMPS][2] PROGMEM = { + {1, 841}, + {54, 255}, + {107, 209}, + {160, 184}, + {213, 166}, + {266, 153}, + {319, 142}, + {372, 132}, + {425, 124}, + {478, 116}, + {531, 108}, + {584, 101}, + {637, 93}, + {690, 86}, + {743, 78}, + {796, 70}, + {849, 61}, + {902, 50}, + {955, 34}, + {1008, 3} +}; +#endif + +#ifdef TEMP_AD595 +#include "analog.h" +#endif + +void temp_init() { + uint8_t i; + for (i = 0; i < NUM_TEMP_SENSORS; i++) { + switch(temp_sensors[i].temp_type) { + #ifdef TEMP_MAX6675 + // initialised when read +/* case TT_MAX6675: + break;*/ + #endif + + #ifdef TEMP_THERMISTOR + // handled by analog_init() +/* case TT_THERMISTOR: + break;*/ + #endif + + #ifdef TEMP_AD595 + // handled by analog_init() +/* case TT_AD595: + break;*/ + #endif + + #ifdef GEN3 + case TT_INTERCOM: + intercom_init(); + update_send_cmd(0); + break; + #endif + } + } +} + +void temp_sensor_tick() { + uint8_t i = 0; + for (; i < NUM_TEMP_SENSORS; i++) { + if (temp_sensors_runtime[i].next_read_time) { + temp_sensors_runtime[i].next_read_time--; + } + else { + uint16_t temp = 0; + //time to deal with this temp sensor + switch(temp_sensors[i].temp_type) { + #ifdef TEMP_MAX6675 + case TT_MAX6675: + #ifdef PRR + PRR &= ~MASK(PRSPI); + #elif defined PRR0 + PRR0 &= ~MASK(PRSPI); + #endif + + SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0); + + // enable TT_MAX6675 + WRITE(SS, 0); + + // ensure 100ns delay - a bit extra is fine + delay(1); + + // read MSB + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp = SPDR; + temp <<= 8; + + // read LSB + SPDR = 0; + for (;(SPSR & MASK(SPIF)) == 0;); + temp |= SPDR; + + // disable TT_MAX6675 + WRITE(SS, 1); + + temp_sensors_runtime[i].temp_flags = 0; + if ((temp & 0x8002) == 0) { + // got "device id" + temp_sensors_runtime[i].temp_flags |= PRESENT; + if (temp & 4) { + // thermocouple open + temp_sensors_runtime[i].temp_flags |= TCOPEN; + } + else { + temp = temp >> 3; + } + } + + // this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms + temp_sensors_runtime[i].next_read_time = 25; + + break; + #endif /* TEMP_MAX6675 */ + + #ifdef TEMP_THERMISTOR + case TT_THERMISTOR: + do { + uint8_t j; + //Read current temperature + temp = analog_read(temp_sensors[i].temp_pin); + + //Calculate real temperature based on lookup table + for (j = 1; j < NUMTEMPS; j++) { + if (pgm_read_word(&(temptable[j][0])) > temp) { + // multiply by 4 because internal temp is stored as 14.2 fixed point + temp = pgm_read_word(&(temptable[j][1])) * 4 + (pgm_read_word(&(temptable[j][0])) - temp) * 4 * (pgm_read_word(&(temptable[j-1][1])) - pgm_read_word(&(temptable[j][1]))) / (pgm_read_word(&(temptable[j][0])) - pgm_read_word(&(temptable[j-1][0]))); + break; + } + } + + //Clamp for overflows + if (j == NUMTEMPS) + temp = temptable[NUMTEMPS-1][1] * 4; + + temp_sensors_runtime[i].next_read_time = 0; + } while (0); + break; + #endif /* TEMP_THERMISTOR */ + + #ifdef TEMP_AD595 + case TT_AD595: + temp = analog_read(temp_pin); + + // convert + // >>8 instead of >>10 because internal temp is stored as 14.2 fixed point + temp = (temp * 500L) >> 8; + + temp_sensors_runtime[i].next_read_time = 0; + + break; + #endif /* TEMP_AD595 */ + + #ifdef TEMP_PT100 + case TT_PT100: + #warning TODO: PT100 code + break + #endif /* TEMP_PT100 */ + + #ifdef GEN3 + case TT_INTERCOM: + temp = get_read_cmd() << 2; + + start_send(); + + temp_sensors_runtime[i].next_read_time = 0; + + break; + #endif /* GEN3 */ + } + temp_sensors_runtime[i].last_read_temp = temp; + + if (labs(temp - temp_sensors_runtime[i].target_temp) < TEMP_HYSTERESIS) { + if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME) + temp_sensors_runtime[i].temp_residency++; + } + else { + temp_sensors_runtime[i].temp_residency = 0; + } + + if (temp_sensors[i].heater_index < NUM_HEATERS) { + heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp); + } + } + } +} + +uint8_t temp_achieved() { + uint8_t i, all_ok = 255; + for (i = 0; i < NUM_TEMP_SENSORS; i++) { + if (temp_sensors_runtime[i].temp_residency < TEMP_RESIDENCY_TIME) + all_ok = 0; + } + return all_ok; +} + +void temp_set(uint8_t index, uint16_t temperature) { + temp_sensors_runtime[index].target_temp = temperature; + temp_sensors_runtime[index].temp_residency = 0; +#ifdef GEN3 + if (temp_sensors[index].temp_type == TT_INTERCOM) + update_send_cmd(temperature >> 2); +#endif +} + +uint16_t temp_get(uint8_t index) { + return temp_sensors_runtime[index].last_read_temp; +} + +// extruder doesn't have sersendf_P +#ifndef EXTRUDER +void temp_print(uint8_t index) { + uint8_t c = 0; + + c = (temp_sensors_runtime[index].last_read_temp & 3) * 25; + + sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c); +} +#endif diff --git a/extruder/temp.h b/extruder/temp.h deleted file mode 120000 index 5f7682d..0000000 --- a/extruder/temp.h +++ /dev/null @@ -1 +0,0 @@ -../temp.h \ No newline at end of file diff --git a/extruder/temp.h b/extruder/temp.h new file mode 100644 index 0000000..b00ee95 --- /dev/null +++ b/extruder/temp.h @@ -0,0 +1,29 @@ +#ifndef _TEMP_H +#define _TEMP_H + +#include + +/* +NOTES + +no point in specifying a port- all the different temp sensors we have must be on a particular port. The MAX6675 must be on the SPI, and the thermistor and AD595 must be on an analog port. + +we still need to specify which analog pins we use in machine.h for the analog sensors however, otherwise the analog subsystem won't read them. +*/ + +#define temp_tick temp_sensor_tick + +void temp_init(void); + +void temp_sensor_tick(void); + +uint8_t temp_achieved(void); + +void temp_set(uint8_t index, uint16_t temperature); +uint16_t temp_get(uint8_t index); + +void temp_print(uint8_t index); + +uint16_t temp_read(uint8_t index); + +#endif /* _TIMER_H */ diff --git a/extruder/watchdog.c b/extruder/watchdog.c deleted file mode 120000 index f5d6bfa..0000000 --- a/extruder/watchdog.c +++ /dev/null @@ -1 +0,0 @@ -../watchdog.c \ No newline at end of file diff --git a/extruder/watchdog.c b/extruder/watchdog.c new file mode 100644 index 0000000..28cbe32 --- /dev/null +++ b/extruder/watchdog.c @@ -0,0 +1,47 @@ + +#include "watchdog.h" + +#ifdef USE_WATCHDOG + +#include +#include + +#include "arduino.h" +#include "serial.h" + +volatile uint8_t wd_flag = 0; + +// uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); +// void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3"))); +// void get_mcusr(void) { +// mcusr_mirror = MCUSR; +// MCUSR = 0; +// wdt_disable(); +// } + +ISR(WDT_vect) { + // watchdog has tripped- no main loop activity for 0.5s, probably a bad thing + // if watchdog fires again, we will reset + // perhaps we should do something more intelligent in this interrupt? + wd_flag |= 1; +} + +void wd_init() { + // check if we were reset by the watchdog +// if (mcusr_mirror & MASK(WDRF)) +// serial_writestr_P(PSTR("Watchdog Reset!\n")); + + // 0.25s timeout, interrupt and system reset + wdt_enable(WDTO_500MS); + WDTCSR |= MASK(WDIE); +} + +void wd_reset() { + wdt_reset(); + if (wd_flag) { + WDTCSR |= MASK(WDIE); + wd_flag &= ~1; + } +} + +#endif /* USE_WATCHDOG */ diff --git a/extruder/watchdog.h b/extruder/watchdog.h deleted file mode 120000 index 20df3e8..0000000 --- a/extruder/watchdog.h +++ /dev/null @@ -1 +0,0 @@ -../watchdog.h \ No newline at end of file diff --git a/extruder/watchdog.h b/extruder/watchdog.h new file mode 100644 index 0000000..bac43c9 --- /dev/null +++ b/extruder/watchdog.h @@ -0,0 +1,22 @@ +#ifndef _WATCHDOG_H +#define _WATCHDOG_H + +#include "config.h" + +#ifdef USE_WATCHDOG + +// initialize +void wd_init(void) __attribute__ ((cold)); + +// reset timeout- must be called periodically or we reboot +void wd_reset(void); + +// notable lack of disable function + +#else /* USE_WATCHDOG */ + +#define wd_init() /* empty */ +#define wd_reset() /* empty */ + +#endif /* USE_WATCHDOG */ +#endif /* _WATCHDOG_H */ diff --git a/intercom.c b/intercom.c deleted file mode 120000 index a627b1f..0000000 --- a/intercom.c +++ /dev/null @@ -1 +0,0 @@ -extruder/intercom.c \ No newline at end of file diff --git a/intercom.c b/intercom.c new file mode 100644 index 0000000..7cab163 --- /dev/null +++ b/intercom.c @@ -0,0 +1,219 @@ +#include "intercom.h" + +#include + +#include "config.h" +#include "delay.h" + +#ifdef GEN3 +#define INTERCOM_BAUD 57600 + +#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); WRITE(RX_ENABLE_PIN,0); } while(0) +#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); WRITE(RX_ENABLE_PIN,0); } while(0) + +/* + Defines a super simple intercom interface using the RS485 modules + + Host will say: START1 START2 PWM_CMD PWM_CHK + Extruder will reply: START1 START2 TMP_CMD TMP_CHK + + CHK = 255-CMD, if they match do the work, if not, ignore this packet + + in a loop +*/ + + +#define START1 0xAA +#define START2 0x55 + +typedef enum { + SEND_START1, + SEND_START2, + SEND_CMD, + SEND_CHK, + SEND_DONE, + + READ_START1, + READ_START2, + READ_CMD, + READ_CHK, +} intercom_state_e; + + +intercom_state_e state = READ_START1; +uint8_t cmd, chk, send_cmd, read_cmd; + +void intercom_init(void) +{ +#ifdef HOST + #if INTERCOM_BAUD > 38401 + UCSR1A = MASK(U2X1); + UBRR1 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5); + #else + UCSR1A = 0; + UBRR1 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5); + #endif + UCSR1B = MASK(RXEN1) | MASK(TXEN1); + UCSR1C = MASK(UCSZ11) | MASK(UCSZ10); + + UCSR1B |= MASK(RXCIE1) | MASK(TXCIE1); +#else + #if INTERCOM_BAUD > 38401 + UCSR0A = MASK(U2X0); + UBRR0 = (((F_CPU / 8) / INTERCOM_BAUD) - 0.5); + #else + UCSR0A = 0; + UBRR0 = (((F_CPU / 16) / INTERCOM_BAUD) - 0.5); + #endif + UCSR0B = MASK(RXEN0) | MASK(TXEN0); + UCSR0C = MASK(UCSZ01) | MASK(UCSZ00); + + UCSR0B |= MASK(RXCIE0) | MASK(TXCIE0); +#endif +} + +void update_send_cmd(uint8_t new_send_cmd) { + send_cmd = new_send_cmd; +} + +uint8_t get_read_cmd(void) { + return read_cmd; +} + +static void write_byte(uint8_t val) { +#ifdef HOST + UDR1 = val; +#else + UDR0 = val; +#endif +} + + +void start_send(void) { + state = SEND_START1; + enable_transmit(); + delay_us(15); + //Enable interrupts so we can send next characters +#ifdef HOST + UCSR1B |= MASK(UDRIE1); +#else + UCSR0B |= MASK(UDRIE0); +#endif +} + +static void finish_send(void) { + state = READ_START1; + disable_transmit(); +} + + +/* + Interrupts, UART 0 for mendel +*/ +#ifdef HOST +ISR(USART1_RX_vect) +#else +ISR(USART_RX_vect) +#endif +{ + static uint8_t c; + +#ifdef HOST + c = UDR1; + UCSR1A &= ~MASK(FE1) & ~MASK(DOR1) & ~MASK(UPE1); +#else + c = UDR0; + UCSR0A &= ~MASK(FE0) & ~MASK(DOR0) & ~MASK(UPE0); +#endif + + if (state >= READ_START1) { + + switch(state) { + case READ_START1: + if (c == START1) state = READ_START2; + break; + case READ_START2: + if (c == START2) state = READ_CMD; + else state = READ_START1; + break; + case READ_CMD: + cmd = c; + state = READ_CHK; + break; + case READ_CHK: + chk = c; + + if (chk == 255 - cmd) { + //Values are correct, do something useful + WRITE(DEBUG_LED,1); + read_cmd = cmd; +#ifdef EXTRUDER + start_send(); +#endif + } + else + { + state = READ_START1; + } + break; + default: + break; + } + } + +} + +#ifdef HOST +ISR(USART1_TX_vect) +#else +ISR(USART_TX_vect) +#endif +{ + if (state == SEND_DONE) { + finish_send(); + + +#ifdef HOST + UCSR1B &= ~MASK(TXCIE1); +#else + UCSR0B &= ~MASK(TXCIE0); +#endif + } +} + +#ifdef HOST +ISR(USART1_UDRE_vect) +#else +ISR(USART_UDRE_vect) +#endif +{ + switch(state) { + case SEND_START1: + write_byte(START1); + state = SEND_START2; + break; + case SEND_START2: + write_byte(START2); + state = SEND_CMD; + break; + case SEND_CMD: + write_byte(send_cmd); + state = SEND_CHK; + break; + case SEND_CHK: + write_byte(255 - send_cmd); + state = SEND_DONE; +#ifdef HOST + UCSR1B &= ~MASK(UDRIE1); + UCSR1B |= MASK(TXCIE1); +#else + UCSR0B &= ~MASK(UDRIE0); + UCSR0B |= MASK(TXCIE0); +#endif + break; + default: + break; + } +} + +#endif /* GEN3 */ diff --git a/intercom.h b/intercom.h deleted file mode 120000 index c515963..0000000 --- a/intercom.h +++ /dev/null @@ -1 +0,0 @@ -extruder/intercom.h \ No newline at end of file diff --git a/intercom.h b/intercom.h new file mode 100644 index 0000000..5a6ab8e --- /dev/null +++ b/intercom.h @@ -0,0 +1,17 @@ +#ifndef _INTERCOM_H +#define _INTERCOM_H + +#include + +// initialise serial subsystem +void intercom_init(void); + +//Update the message we are sending over intercom +void update_send_cmd(uint8_t new_send_cmd); + +void start_send(void); + +//Read the message we are receiving over intercom +uint8_t get_read_cmd(void); + +#endif /* _INTERCOM_H */ diff --git a/mendel_cmd b/mendel_cmd deleted file mode 120000 index 75dbe33..0000000 --- a/mendel_cmd +++ /dev/null @@ -1 +0,0 @@ -func.sh \ No newline at end of file diff --git a/mendel_cmd b/mendel_cmd new file mode 100755 index 0000000..cc2e469 --- /dev/null +++ b/mendel_cmd @@ -0,0 +1,312 @@ +#!/bin/bash + +# +# this file is designed to be sourced into your current shell like this: +# +# source ./func.sh +# +# and then used like this: +# +# $ mendel_cmd G1 X100 +# $ mendel_cmd M250 +# +# {X:4200,Y:0,Z:0,E:0,F:300,c:19334400} +# {X:4200,Y:0,Z:0,E:0,F:300,c:0} +# Q1/1E +# $ mendel_readsym_uint8 mb_head +# 1 +# $ mendel_readsym_target startpoint +# X: 2100 +# Y: 0 +# Z: 0 +# E: 0 +# F: 300 +# $ mendel_readsym_mb +# [0] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [HEAD,TAIL:1] { +# eX: 4200 eY: 0 eZ: 0 eE: 0 eF: 300 +# flags: 120 +# dX: 4200 dY: 0 dZ: 0 dE: 0 +# cX: -2100 cY: -2100 cZ: -2100 cE: -2100 +# ts: 4200 +# c: 19334400 ec: 0 n: 0 +# } +# [2] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [3] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [4] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [5] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [6] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } +# [7] { +# eX: 0 eY: 0 eZ: 0 eE: 0 eF: 0 +# flags: 0 +# dX: 0 dY: 0 dZ: 0 dE: 0 +# cX: 0 cY: 0 cZ: 0 cE: 0 +# ts: 0 +# c: 0 ec: 0 n: 0 +# } + + +mendel_setup() { + stty 115200 raw ignbrk -hup -echo ixoff < /dev/arduino +} + +mendel_reset() { + stty hup < /dev/arduino + stty hup < /dev/arduino + mendel_setup +} + +mendel_talk() { + ( cat <&3 & cat >&3; kill $! ; ) 3<>/dev/arduino +} + +mendel_cmd() { + ( + local IFS=$' \t\n' + local RSC=0 + local cmd="$*" + echo "$cmd" >&3; + local REPLY="" + while ! [[ "$REPLY" =~ ^OK ]] && ! [[ "$REPLY" =~ ^ok ]] + do + read -u 3 + echo "${REPLY##ok }" + if [[ "$REPLY" =~ ^RESEND ]] || [[ "$REPLY" =~ ^rs ]] + then + if [ "$RSC" -le 3 ] + then + echo "$cmd" >&3 + RSC=$(( $RSC + 1 )) + else + REPLY="OK" + echo "Too many retries: aborting" >&2 + fi + fi + done + ) 3<>/dev/arduino; +} + +mendel_cmd_hr() { + ( + local IFS=$' \t\n' + local cmd="$*" + local RSC=0 + echo "$cmd" >&3 + echo "S> $cmd" + local REPLY="" + while ! [[ "$REPLY" =~ ^OK ]] && ! [[ "$REPLY" =~ ^ok ]] + do + read -u 3 + echo "&3 + echo "S> $cmd" + RSC=$(( $RSC + 1)) + else + REPLY="OK" + echo "Too many retries: aborting" >&2 + fi + fi + done + ) 3<>/dev/arduino; +} + +mendel_print() { + ( + for F in "$@" + do + local IFS=$'\n' + for L in $(< $F) + do + mendel_cmd_hr "$L" + done + done + ) +} + +mendel_readsym() { + ( + local IFS=$' \t\n' + local sym=$1 + if [ -n "$sym" ] + then + if [[ "$sym" =~ ^(0?x?[0-9A-Fa-f]+)(:([0-9]+))?$ ]] + then + local ADDR=$(( ${BASH_REMATCH[1]} )) + local SIZE=$(( ${BASH_REMATCH[3]} )) + if [ "$SIZE" -le 1 ] + then + SIZE=1 + fi + mendel_cmd "M253 S$ADDR P$SIZE" + else + make mendel.sym &>/dev/null + if egrep -q '\b'$sym'\b' mendel.sym + then + local ADDR=$(( $(egrep '\b'$sym'\b' mendel.sym | cut -d\ -f1) )) + local SIZE=$(egrep '\b'$sym'\b' mendel.sym | cut -d+ -f2) + mendel_cmd "M253 S$ADDR P$SIZE" + else + echo "unknown symbol: $sym" + fi + fi + else + echo "what symbol?" > /dev/fd/2 + fi + ) +} + +mendel_readsym_uint8() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e 'printf "%u\n", eval "0x".$ARGV[0]' $val +} + +mendel_readsym_int8() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e 'printf "%d\n", ((eval "0x".$ARGV[0]) & 0x7F) - (((eval "0x".$ARGV[0]) & 0x80)?0x80:0)' $val +} + +mendel_readsym_uint16() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e '$ARGV[0] =~ m#(..)(..)# && printf "%u\n", eval "0x$2$1"' $val +} + +mendel_readsym_int16() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e '$ARGV[0] =~ m#(..)(..)# && printf "%d\n", ((eval "0x$2$1") & 0x7FFF) - (((eval "0x$2$1") & 0x8000)?0x8000:0)' $val +} + +mendel_readsym_uint32() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e '$ARGV[0] =~ m#(..)(..)(..)(..)# && printf "%u\n", eval "0x$4$3$2$1"' $val +} + +mendel_readsym_int32() { + local sym=$1 + local val=$(mendel_readsym $sym) + perl -e '$ARGV[0] =~ m#(..)(..)(..)(..)# && printf "%d\n", eval "0x$4$3$2$1"' $val +} + +mendel_readsym_target() { + local sym=$1 + local val=$(mendel_readsym "$sym") + if [ -n "$val" ] + then + perl -e '@a = qw/X Y Z E F/; $c = 0; while (length $ARGV[0]) { $ARGV[0] =~ s#^(..)(..)(..)(..)##; printf "%s: %d\n", $a[$c], eval "0x$4$3$2$1"; $c++; }' "$val" + fi +} + +mendel_readsym_mb() { + local val=$(mendel_readsym movebuffer) + local mbhead=$(mendel_readsym mb_head) + local mbtail=$(mendel_readsym mb_tail) + perl - <<'ENDPERL' -- $val $mbhead $mbtail + $i = -1; + @a = qw/eX 4 eY 4 eZ 4 eE 4 eF 4 flags 9 dX 12 dY 4 dZ 4 dE 4 cX 12 cY 4 cZ 4 cE 4 ts 12 c 12 rs 4 sn 4 cm 4 n 4 rs 1/; + $c = 0; + $c = 1234567; + while (length $ARGV[1]) { + if ($c > ($#a / 2)) { + $i++; + $c = 0; + printf "\n}\n" + if ($i > 0); + printf "[%s%d] {\n", (($i == $ARGV[2])?"HEAD":"").(($ARGV[2] == $ARGV[3] && $ARGV[2] == $i)?",":"").(($i == $ARGV[3])?"TAIL":"").(($i == $ARGV[2] || $i == $ARGV[3])?":":""), $i + } + if ($a[$c * 2 + 1] & 8) { + printf "\n"; + } + if (($a[$c * 2 + 1] & 7) == 4) { + $ARGV[1] =~ s#^(..)(..)(..)(..)##; + printf "\t%s: %d", $a[$c * 2], eval "0x$4$3$2$1"; + } + elsif (($a[$c * 2 + 1] & 7) == 1) { + $ARGV[1] =~ s#^(..)##; + printf "\t%s: %d", $a[$c * 2], eval "0x$1"; + } + $c++; + } + printf "\n}\n"; +ENDPERL +} + +mendel_heater_pid() { + local P=$(mendel_readsym_int16 heater_p) + local I=$(mendel_readsym_int16 heater_i) + local D=$(mendel_readsym_int16 heater_d) + + local PF=$(mendel_readsym_int32 p_factor) + local IF=$(mendel_readsym_int32 i_factor) + local DF=$(mendel_readsym_int32 d_factor) + + local O=$(mendel_readsym_uint8 0x27) + local T=$(mendel_cmd M105 | cut -d\ -f2 | cut -d/ -f1) + + echo "P=$P pf=$PF r="$(($P * $PF)) + echo "I=$I if=$IF r="$(($I * $IF)) + echo "D=$D df=$DF r="$(($D * $DF)) + echo "R="$(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024 + echo "R="$(( $(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024 )) + echo "R="$(( $(( $(( $(($P * $PF)) + $(($I * $IF)) + $(($D * $DF)) )) / 1024 )) + 128 )) + echo "O=$O T=$T" +} + +if [[ "$0" =~ ^mendel_(setup|reset|cmd|readsym|heater_pid) ]] +then + eval "$0" "$@" +fi + +if [[ "$1" =~ ^mendel_(setup|reset|cmd|readsym|heater_pid) ]] +then + eval "$@" +fi From 0816cecf1ea85ff38717c0256cec92b025c5b538 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Mon, 13 Dec 2010 21:34:03 +1100 Subject: [PATCH 76/82] UNTESTED fuse programming support --- Makefile | 10 +++++++++- README | 15 +++++++++++++++ fuses.h | 27 +++++++++++++++++++++++++++ mendel.c | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 fuses.h diff --git a/Makefile b/Makefile index 362b134..5d8019e 100644 --- a/Makefile +++ b/Makefile @@ -122,8 +122,16 @@ program: $(PROGRAM).hex config.h $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U flash:w:$^ stty 115200 raw ignbrk -hup -echo ixoff < $(PROGPORT) +program-fuses: + avr-objdump -s -j .fuse mendel.o | perl -ne '/\s0000\s([0-9a-f]{2})/ && print "$$1\n"' > lfuse + avr-objdump -s -j .fuse mendel.o | perl -ne '/\s0000\s..([0-9a-f]{2})/ && print "$$1\n"' > hfuse + avr-objdump -s -j .fuse mendel.o | perl -ne '/\s0000\s....([0-9a-f]{2})/ && print "$$1\n"' > efuse + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U lfuse:w:lfuse + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U hfuse:w:hfuse + $(AVRDUDE) -cstk500v1 -b$(PROGBAUD) -p$(MCU_TARGET) -P$(PROGPORT) -C$(AVRDUDECONF) -U efuse:w:efuse + clean: - rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ *fuse size: $(PROGRAM).elf @echo " SIZE Atmega168 Atmega328p Atmega644" diff --git a/README b/README index cd05cf9..d27534a 100644 --- a/README +++ b/README @@ -18,10 +18,25 @@ Rewrite of Reprap Mendel firmware: 2) check programming settings in Makefile 3) make 4) make program +4a) if programming blank chip, make program-fuses 5) ./sender.sh 6) have a play, go to 1) if not right 7) try printing something! +############################################################################## +# # +# Requirements # +# # +############################################################################## + +Compile: + gnu make + binutils, gcc, etc built for avr target (avr-gcc, avr-as, etc) + avr-libc +Program: + avrdude + something that avrdude supports: bootloader, separate programmer, whatever + ############################################################################## # # # License # diff --git a/fuses.h b/fuses.h new file mode 100644 index 0000000..4f6e411 --- /dev/null +++ b/fuses.h @@ -0,0 +1,27 @@ +#if defined (__AVR_ATmega168__) +FUSES = { + .low = FUSE_CKSEL3 & FUSE_SUT0, + .high = FUSE_SPIEN, + .extended = FUSE_BOOTSZ1 & FUSE_BOOTSZ0, +}; +#elif defined (__AVR_ATmega328P__) +FUSES = { + .low = FUSE_CKSEL3 & FUSE_SUT0, + .high = FUSE_SPIEN & FUSE_BOOTSZ0 & FUSE_BOOTSZ1, + .extended = EFUSE_DEFAULT, +}; +#elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) +FUSES = { + .low = FUSE_CKSEL3 & FUSE_SUT0, + .high = FUSE_SPIEN & FUSE_BOOTSZ0 & FUSE_BOOTSZ1, + .extended = EFUSE_DEFAULT, +}; +#elif defined (__AVR_ATmega1280__) +FUSES = { + .low = FUSE_CKSEL3 & FUSE_SUT0, + .high = FUSE_SPIEN & FUSE_BOOTSZ0 & FUSE_BOOTSZ1, + .extended = EFUSE_DEFAULT, +}; +#else +#warning No fuse definitions for this chip in fuses.h! +#endif diff --git a/mendel.c b/mendel.c index 919822b..e36387d 100644 --- a/mendel.c +++ b/mendel.c @@ -3,6 +3,7 @@ #include #include "config.h" +#include "fuses.h" #include "serial.h" #include "dda_queue.h" From 06ad86350554d9f7c48469c2b45fd1f0f17c192f Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Fri, 17 Dec 2010 15:14:18 +1100 Subject: [PATCH 77/82] tell heater_tick which temp sensor it's attached to --- heater.c | 12 +++++++----- heater.h | 2 +- temp.c | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/heater.c b/heater.c index 7d0d759..f8608d2 100644 --- a/heater.c +++ b/heater.c @@ -94,10 +94,11 @@ void heater_init() { heaters_pid[i].i_limit = DEFAULT_I_LIMIT; } } - #endif + #endif /* NUM_HEATERS > 0 */ } void heater_save_settings() { + #if NUM_HEATERS > 0 uint8_t i; for (i = 0; i < NUM_HEATERS; i++) { eeprom_write_dword((uint32_t *) &EE_factors[i].EE_p_factor, heaters_pid[i].p_factor); @@ -105,10 +106,11 @@ void heater_save_settings() { eeprom_write_dword((uint32_t *) &EE_factors[i].EE_d_factor, heaters_pid[i].d_factor); eeprom_write_word((uint16_t *) &EE_factors[i].EE_i_limit, heaters_pid[i].i_limit); } + #endif /* NUM_HEATERS > 0 */ } -void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { - #if NUM_HEATERS > 0 +void heater_tick(uint8_t h, uint8_t t, uint16_t current_temp, uint16_t target_temp) { + #if (NUM_HEATERS > 0) && (NUM_TEMP_SENSORS > 0) int16_t heater_p; int16_t heater_d; uint8_t pid_output; @@ -208,12 +210,12 @@ void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp) { if (labs(current_temp - heaters_runtime[h].sane_temperature) > TEMP_HYSTERESIS) { // no change, or change in wrong direction for a long time- heater is broken! pid_output = 0; - sersendf_P(PSTR("!! heater %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter); + sersendf_P(PSTR("!! heater %d or temp sensor %d broken- temp is %d.%dC, target is %d.%dC, didn't reach %d.%dC in %d0 milliseconds\n"), h, t, current_temp >> 2, (current_temp & 3) * 25, target_temp >> 2, (target_temp & 3) * 25, heaters_runtime[h].sane_temperature >> 2, (heaters_runtime[h].sane_temperature & 3) * 25, heaters_runtime[h].sanity_counter); } #endif /* HEATER_SANITY_CHECK */ heater_set(h, pid_output); - #endif /* if NUM_HEATERS > 0 */ + #endif /* if NUM_HEATERS > 0 && NUM_TEMP_SENSORS > 0 */ } void heater_set(uint8_t index, uint8_t value) { diff --git a/heater.h b/heater.h index fdc9dc9..aca8547 100644 --- a/heater.h +++ b/heater.h @@ -10,7 +10,7 @@ void heater_init(void); void heater_save_settings(void); void heater_set(uint8_t index, uint8_t value); -void heater_tick(uint8_t h, uint16_t current_temp, uint16_t target_temp); +void heater_tick(uint8_t h, uint8_t t, uint16_t current_temp, uint16_t target_temp); void pid_set_p(uint8_t index, int32_t p); void pid_set_i(uint8_t index, int32_t i); diff --git a/temp.c b/temp.c index 4809218..39fc866 100644 --- a/temp.c +++ b/temp.c @@ -235,7 +235,7 @@ void temp_sensor_tick() { } if (temp_sensors[i].heater_index < NUM_HEATERS) { - heater_tick(temp_sensors[i].heater_index, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp); + heater_tick(temp_sensors[i].heater_index, i, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp); } } } From a8819fbb1bc2ba97a5f95ddc74c3126cabfcfa93 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 19 Dec 2010 07:08:48 +1100 Subject: [PATCH 78/82] add dummy sensor, reformat temperature --- temp.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/temp.c b/temp.c index 39fc866..c177038 100644 --- a/temp.c +++ b/temp.c @@ -9,7 +9,8 @@ typedef enum { TT_MAX6675, TT_AD595, TT_PT100, - TT_INTERCOM + TT_INTERCOM, + TT_DUMMY, } temp_types; typedef enum { @@ -213,7 +214,7 @@ void temp_sensor_tick() { break #endif /* TEMP_PT100 */ - #ifdef GEN3 + #ifdef TEMP_INTERCOM case TT_INTERCOM: temp = get_read_cmd() << 2; @@ -222,7 +223,21 @@ void temp_sensor_tick() { temp_sensors_runtime[i].next_read_time = 0; break; - #endif /* GEN3 */ + #endif /* TEMP_INTERCOM */ + + #ifdef TEMP_DUMMY + case TT_DUMMY: + temp = temp_sensors_runtime[i].last_read_temp; + + if (temp_sensors_runtime[i].target_temp > temp) + temp++; + else if (temp_sensors_runtime[i].target_temp < temp) + temp--; + + temp_sensors_runtime[i].next_read_time = 0; + + break; + #endif /* TEMP_DUMMY */ } temp_sensors_runtime[i].last_read_temp = temp; @@ -270,6 +285,6 @@ void temp_print(uint8_t index) { c = (temp_sensors_runtime[index].last_read_temp & 3) * 25; - sersendf_P(PSTR("T: %u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c); + sersendf_P(PSTR("T:%u.%u\n"), temp_sensors_runtime[index].last_read_temp >> 2, c); } #endif From ecc0d6e3ef9ef354b9803e4d05533d8067d34caa Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Sun, 19 Dec 2010 07:09:19 +1100 Subject: [PATCH 79/82] fix waitfor temperature, for M109 and friends --- dda.c | 42 +++++++++++++++++++++--------------------- dda_queue.c | 12 +++++++++++- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/dda.c b/dda.c index 3e97eee..0bdedaf 100644 --- a/dda.c +++ b/dda.c @@ -330,32 +330,32 @@ void dda_start(DDA *dda) { // keep dda->live = 0 } else { - if (dda->waitfor_temp) { +/* if (dda->waitfor_temp) { #ifndef REPRAP_HOST_COMPATIBILITY serial_writestr_P(PSTR("Waiting for target temp\n")); #endif } - else { - // ensure steppers are ready to go - steptimeout = 0; - power_on(); - x_enable(); - y_enable(); - if (dda->z_delta) - z_enable(); + else {*/ + // ensure steppers are ready to go + steptimeout = 0; + power_on(); + x_enable(); + y_enable(); + if (dda->z_delta) + z_enable(); - // set direction outputs - x_direction(dda->x_direction); - y_direction(dda->y_direction); - z_direction(dda->z_direction); - e_direction(dda->e_direction); - - #ifdef DC_EXTRUDER - if (dda->e_delta) - heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM); - #endif - - } + // set direction outputs + x_direction(dda->x_direction); + y_direction(dda->y_direction); + z_direction(dda->z_direction); + e_direction(dda->e_direction); + + #ifdef DC_EXTRUDER + if (dda->e_delta) + heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM); + #endif + +// } // ensure this dda starts dda->live = 1; diff --git a/dda_queue.c b/dda_queue.c index ad33992..3b4ab66 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -32,6 +32,7 @@ void queue_step() { // do our next step if (movebuffer[mb_tail].live) { if (movebuffer[mb_tail].waitfor_temp) { + setTimer(movebuffer[mb_tail].c >> 8); if (temp_achieved()) { movebuffer[mb_tail].live = movebuffer[mb_tail].waitfor_temp = 0; serial_writestr_P(PSTR("Temp achieved\n")); @@ -90,7 +91,16 @@ void next_move() { // next item uint8_t t = mb_tail + 1; t &= (MOVEBUFFER_SIZE - 1); - dda_start(&movebuffer[t]); + if (movebuffer[t].waitfor_temp) { + #ifndef REPRAP_HOST_COMPATIBILITY + serial_writestr_P(PSTR("Waiting for target temp\n")); + #endif + movebuffer[t].live = 1; + setTimer(movebuffer[t].c >> 8); + } + else { + dda_start(&movebuffer[t]); + } mb_tail = t; } else From 19e3c24835b06e11f137e62e85f9a36a54e8bfcf Mon Sep 17 00:00:00 2001 From: Jacky2k Date: Thu, 6 Jan 2011 10:44:06 +1100 Subject: [PATCH 80/82] fix arithmetic overflow Signed-off-by: Michael Moon --- gcode_parse.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index e9fc162..3673be7 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -60,10 +60,14 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) e--; // scale factors - if (multiplicand != 1) - r *= multiplicand; - if (denominator != 1) - r /= denominator; +// if (multiplicand != 1) +// r *= multiplicand; +// if (denominator != 1) +// r /= denominator; + + int32_t rnew1 = r * (multiplicand / denominator) + int32_t rnew2 = r * (multiplicand % denominator) + r = rnew1 + rnew2; // sign if (df->sign) From 24e95f0707847b31afb46dc4378c3c267b009649 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 6 Jan 2011 18:22:17 +1100 Subject: [PATCH 81/82] fix typo --- gcode_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 3673be7..4385a7f 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -65,8 +65,8 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) // if (denominator != 1) // r /= denominator; - int32_t rnew1 = r * (multiplicand / denominator) - int32_t rnew2 = r * (multiplicand % denominator) + int32_t rnew1 = r * (multiplicand / denominator); + int32_t rnew2 = r * (multiplicand % denominator); r = rnew1 + rnew2; // sign From 319468c7079a6fc8c8c7657d8842722cf8f00828 Mon Sep 17 00:00:00 2001 From: Michael Moon Date: Thu, 6 Jan 2011 18:22:17 +1100 Subject: [PATCH 82/82] fix typo --- gcode_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcode_parse.c b/gcode_parse.c index 3673be7..4385a7f 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -65,8 +65,8 @@ int32_t decfloat_to_int(decfloat *df, int32_t multiplicand, int32_t denominator) // if (denominator != 1) // r /= denominator; - int32_t rnew1 = r * (multiplicand / denominator) - int32_t rnew2 = r * (multiplicand % denominator) + int32_t rnew1 = r * (multiplicand / denominator); + int32_t rnew2 = r * (multiplicand % denominator); r = rnew1 + rnew2; // sign