Firmware/FiveD on Arduino
Rewrite of FiveD firmware for the atmega168-based Arduino by Triffid Hunter
This firmware is loosely based on the official FiveD Firmware, however it uses 100% integer math, and works very hard to minimize/eliminate long math operations in interrupt context.
Contents
- 1 Constant Acceleration
- 2 Transmission of Multiple Commands
- 3 Patches, Enhancements
- 3.1 Make sources buildable with the Arduino IDE.
- 3.2 Achieve C89 compatibility, Arduino IDE's default.
- 3.3 RepRap host software expects a lowercase "ok" for confirmation.
- 3.4 Moved REQUIRE_LINENUMBER and REQUIRE_CHECKSUM #defines to gcode.h as well.
- 3.5 An M-code stuck when receiving G commands and vice-versa.
Constant Acceleration
The official FiveD firmware changes speed by a fixed amount each step, however this also alters the step time. acceleration = dv/dt, so with a fixed dv but a changing dt, acceleration changes during a move. This makes high speeds quite unattainable as the acceleration quickly outstrips the motor's ability to keep up.
FiveD on Arduino contains a constant acceleration implementation.
Transmission of Multiple Commands
FiveD on Arduino has the capability to receive additional commands while working on the first one. This avoids short stops between commands and will allow for even more smooth transitions from one movement to the next in the future.
Patches, Enhancements
As Triffid Hunter is apparently out of town currently (2010-07-03), the Git Repository doesn't allow to upload patches and I don't want to do yet another fork, I'll upload patches here.
To apply those patches, type git apply
in your terminal, inside your local copy of git repo, then copy the text given her into the terminal and hit ctrl-d. Well, I hope it works that way.
Make sources buildable with the Arduino IDE.
--- mendel/mendel.pde | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 mendel/mendel.pde diff --git a/mendel/mendel.pde b/mendel/mendel.pde new file mode 100644 index 0000000..1c3f190 --- /dev/null +++ b/mendel/mendel.pde @@ -0,0 +1,4 @@ + +/* + The existence of this file makes sources buildable with the Arduino IDE. +*/ --
Achieve C89 compatibility, Arduino IDE's default.
--- mendel/serial.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mendel/serial.c b/mendel/serial.c index bce947b..767bdeb 100644 --- a/mendel/serial.c +++ b/mendel/serial.c @@ -146,7 +146,9 @@ void serial_writechar(uint8_t data) void serial_writeblock(void *data, int datalen) { - for (int i = 0; i < datalen; i++) + int i; + + for (i = 0; i < datalen; i++) serial_writechar(((uint8_t *) data)[i]); } @@ -170,15 +172,17 @@ void serial_writechar_P(PGM_P data) void serial_writeblock_P(PGM_P data, int datalen) { - for (int i = 0; i < datalen; i++) + int i; + + for (i = 0; i < datalen; i++) serial_writechar_P(&data[i]); } void serial_writestr_P(PGM_P data) { - uint8_t i = 0; + uint8_t r, i = 0; // yes, this is *supposed* to be assignment rather than comparison, so we break when r is assigned zero - for (uint8_t r; (r = pgm_read_byte(&data[i])); i++) + for (r; (r = pgm_read_byte(&data[i])); i++) serial_writechar(r); } --
RepRap host software expects a lowercase "ok" for confirmation.
--- mendel/gcode.c | 4 ++++ mendel/gcode.h | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/mendel/gcode.c b/mendel/gcode.c index 6d06e08..04a7e71 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -312,7 +312,11 @@ void scan_char(uint8_t c) { ) { process_gcode_command(&next_target); + #ifdef LOWERCASE_OK + serial_writestr_P(PSTR("ok\n")); + #else serial_writestr_P(PSTR("OK\n")); + #endif // expect next line number next_target.N_expected++; diff --git a/mendel/gcode.h b/mendel/gcode.h index bfc9061..4805501 100644 --- a/mendel/gcode.h +++ b/mendel/gcode.h @@ -5,6 +5,9 @@ #include "dda.h" +// host software expectations +#define LOWERCASE_OK + // this is a very crude decimal-based floating point structure. a real floating point would at least have signed exponent typedef struct { uint32_t sign :1; --
Moved REQUIRE_LINENUMBER and REQUIRE_CHECKSUM #defines to gcode.h as well.
--- mendel/Makefile | 4 +--- mendel/gcode.h | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mendel/Makefile b/mendel/Makefile index fcc78f6..3dfd4b6 100644 --- a/mendel/Makefile +++ b/mendel/Makefile @@ -38,8 +38,6 @@ OBJCOPY = $(ARCH)objcopy DEFS = -DF_CPU=$(F_CPU) # DEFS += "-DDEBUG=1" -# DEFS += "-DREQUIRE_LINENUMBER" -# DEFS += "-DREQUIRE_CHECKSUM" OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG # OPTIMIZE = -O0 @@ -103,4 +101,4 @@ size: $(PROGRAM).hex %.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 > $@ \ No newline at end of file + @$(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/mendel/gcode.h b/mendel/gcode.h index 4805501..9fd1795 100644 --- a/mendel/gcode.h +++ b/mendel/gcode.h @@ -7,6 +7,8 @@ // host software expectations #define LOWERCASE_OK +//#define REQUIRE_LINENUMBER +//#define REQUIRE_CHECKSUM // this is a very crude decimal-based floating point structure. a real floating point would at least have signed exponent typedef struct { --
An M-code stuck when receiving G commands and vice-versa.
Testcase:
M105 G1 F100
--> Temperatures would be sent the second time as well.
--- mendel/gcode.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/mendel/gcode.c b/mendel/gcode.c index 04a7e71..c05c598 100644 --- a/mendel/gcode.c +++ b/mendel/gcode.c @@ -335,7 +335,12 @@ void scan_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_checksum = next_target.seen_comment = next_target.checksum_read = next_target.checksum_calculated = 0; + next_target.seen_X = next_target.seen_Y = next_target.seen_Z = \ + next_target.seen_E = next_target.seen_F = next_target.seen_G = \ + next_target.seen_S = next_target.seen_P = next_target.seen_N = \ + next_target.seen_M = next_target.seen_checksum = \ + next_target.seen_comment = next_target.checksum_read = \ + next_target.checksum_calculated = 0; last_field = 0; read_digit.sign = 0; read_digit.mantissa = 0; --