You are on page 1of 75

Firmware

Reprap electronics are controlled by an inexpensive CPU such as the Atmel AVR processor. Atmel processors are what Arduino-based microcontrollers use. These processors are very wimpy compared to even the average ! to " year old PC you #ind in the dump nowadays. $owever% these are CPUs so they do run primitive so#tware. This primitive so#tware they run is the Reprap&s firmware. '# the entire so#tware chain that ma(es the Reprap wor(% the #irmware portion o# it is the closest you get to actual programming. Technically% the term #or what you are doing with #irmware is called cross compiling. This process more or less consists o# the #ollowing steps)

1. *nstall the Arduino *+, on your PC.


-. +ownload some #irmware source code #rom a website. .. /a(e some minor changes to the source code to speci#y what hardware you have. 4. Compile the #irmware using the Arduino *+,. ". Connect the controller to your PC via a U01 cable. 2. Upload the #irmware to your controller&s CPU.

G-codes
A#ter your microcontroller has its #irmware loaded% it is ready to accept 3-codes via the U01 serial port 4a(a C'/ port5. 6ou can either use a program to send these 3-codes over the serial port or you can type them in by hand i# you #ire up a plain-old terminal application li(e hyperterm or minicom. *# you use a program% they generally ta(e #iles in gcode #ormat. 7or all available #irmwares see List of Firmware. The #ollowing is a brie# list o# the most popular #irmware) 0printer /arlin Teacup

The one we will use is Sprinter Firmware

: The Code
<include <avr/pgmspace.h# <include <math.h# "include "fastio.h# "include "Configuration.h# "include "pins.h# "include "Sprinter.h# "include "speed loo!upta"le.h# "include "heater.h# ifdef #S$ %&C '#(CT)*(# "include "arc func.h# endif# ifdef S+S#,,*&T# "include "Sd'at.h# endif# ifdef #S$ $$,&*- S$TT)(.S# "include "store eeprom.h# endif# ifndef C&)T)C%/ S$CT)*( ST%&T# 23define C&)T)C%/ S$CT)*( ST%&T unsigned char sreg 0 S&$.1 cli # define C&)T)C%/ S$CT)*( $(+ S&$. 0 sreg# endif //C&)T)C%/ S$CT)*( ST%&T# 15623void c4a pure virtual

loo! here for descriptions of gcodes7 http7//linu4cnc.org/hand"oo!/gcode/g8 // code.html http7//o"9ects.reprap.org/wi!i/-endel #ser -anual7 &ep&ap.Codes // )mplemented Codes// 8888888888888888888// .: 8; .1 // .1 8 Coordinated -ovement < = > $ // .? 8 C@ %&C // .A 8 CC@ %&C // <.4 8 +well S<seconds; or ,<milliseconds // .?B 8 Come all %4is // .D: 8 #se %"solute Coordinates // .D1 8 #se &elative Coordinates // .D? 8 Set current position to cordinates given // &ep&ap - Codes//

-1:4 8 Set e4truder target temp // -1:E 8 &ead current temp // -1:F 8 'an on // -1:G 8 'an off // .-1:D 8 @ait for e4truder current temp to reach target temp // -114 8 +isplaH current position // Custom - Codes// -?: 8 /ist S+ card // -?1 8 )nit S+ card // -?? 8 &elease S+ card // 2-?A 8 Select S+ file 2-?A filename.g // -?4 8 Start/resume S+ print // -?E 8 ,ause S+ print // 2-?F 8 Set S+ position in "Htes 2-?F S1?A4E // -?G 8 &eport S+ print status // 2-?B 8 Start S+ write 2-?B filename.g // -?D 8 Stop S+ write // filename; 8 +elete file on sd card; 8 // -4? 8 Set output on free pinsI on a non pwm pin 2over pin 1A on an arduino mega3 // use S?EE to turn it on and S: to turn it off. #se , to decide the pin 2-4? ,?A S?EE3 would turn pin ?A on -B: 8 Turn on ,ower SupplH // -B1 8 Turn off ,ower SupplH // 2-B? 8 Set $ codes a"solute 2default // -BA 8 Set $ codes relative while in %"solute Coordinates 2.D:3 mode // I-B4 8 +isa"le steppers until ne4t move // or use S<seconds; to specifH an inactivitH timeoutI after which the steppers will // ."e disa"led. S: to disa"le the timeout -BE 8 Set inactivitH shutdown timer with parameter S<seconds;. To disa"le set // 2Jero 2default -D? 8 Set a4is steps per unit 8 same sHnta4 as .D? // -DA 8 Send a4is steps per unit // 8 Capa"ilities string -11E // -11D 8 Show $ndstopper State // -14: 8 Set "ed target temp // .-1D: 8 @ait for "ed current temp to reach target temp // -?:1 8 Set ma4imum acceleration in units/sK? for print moves 2-?:1 <1::: // 2=1::: -?:? 8 Set ma4imum feedrate that Hour machine can sustain 2-?:A <?:: =?:: // >A:: $1::::3 in mm/sec -?:A 8 Set temperture monitor to S4 // -?:4 8 Set default acceleration7 S normal moves T filament onlH moves 2-?:4 // SA::: TG:::3 in mm/secK? -?:E 8 advanced settings7 minimum travel speed S0while printing T0travel onlHI // <0ma4imum 4H 9er!I >0ma4imum > 9er! -?:F 8 set additional homing offset // -??: 8 set speed factor override percentage S0factor in percent // -??1 8 set e4truder multiplH factor S1:: 88; original $4trude Speed //

-A:1 8 Set ,)+ parameters , ) and + // -A:A 8 ,)+ relaH autotune S<temperature; sets the target temperature. 2default // 2target temperature 0 1E:C -4:: 8 'inish all moves // -E:: 8 stores paramters in $$,&*- // -E:1 8 reads parameters from $$,&*- 2if Hou need to reset them after Hou // .2changed them temporarilH -E:? 8 reverts to the default "factorH settings". =ou still need to store them in // .$$,&*- afterwards if Hou want to -E:A 8 ,rint settings // +e"ug feature / Testing the ,)+ for Cotend // -F:1 8 Show Temp 9itter from $4truder 2min / ma4 value from Cotend // 2Temperature while printing -F:? 8 &eset Temp 9itter from $4truder 2min / ma4 val3 88; +onLt use it while // ,rinting -F:A 8 Show 'ree &am // "define M$&S)*( T$<T "1.A.??T / ?:.:B.?:1?# Stepper -ovement Maria"les// 15Lchar a4is codesN(#- %<)SO 0 5L<LI L=LI L>LI L$ 1float a4is steps per unitN4O 0 %<)S ST$, ,$& #()T 1float ma4 feedrateN4O 0 -%< '$$+&%T$ 1float homing feedrateNO 0 C*-)(. '$$+&%T$ 1"ool a4is relative modesNO 0 %<)S &$/%T)M$ -*+$S float move acceleration 0 %CC$/$&%T)*(1 // (ormal acceleration mm/sK? float retract acceleration 0 &$T&%CT %CC$/$&%T)*(1 // (ormal acceleration mm/sK? 1float ma4 4H 9er! 0 -%< <= P$&Q 1float ma4 J 9er! 0 -%< > P$&Q 1float ma4 e 9er! 0 -%< $ P$&Q 1unsigned long min seg time 0 -)( S$. T)-$ ifdef ,)+T$-,# unsigned int ,)+ Qp 0 ,)+ ,.%)(I ,)+ Qi 0 ,)+ ).%)(I ,)+ Qd 0 1,)+ +.%)( endif# long ma4 acceleration units per sR secondN4O 0 -%< %CC$/$&%T)*( #()TS ,$& SS S$C*(+1 // <I =I > and $ ma4 acceleration in mm/sK? for printing moves or retracts float ma4 start speed units per secondNO 0 // 1 -%< ST%&T S,$$+ #()TS ,$& S$C*(+

long ma4 travel acceleration units per sR secondNO 0 // -%< T&%M$/ %CC$/$&%T)*( #()TS ,$& SS S$C*(+1 // <I =I > ma4 acceleration in mm/sK? for travel moves 1float mintravelfeedrate 0 +$'%#/T -)(T&%M$/'$$+&%T$ 1float minimumfeedrate 0 +$'%#/T -)()-#-'$$+&%T$ 1Nunsigned long a4is steps per sRr secondN(#- %<)S 1unsigned long plateau steps 1Nunsigned long a4is ma4 intervalN(#- %<)S// 1Nunsigned long a4is travel steps per sRr secondN(#- %<)S// 1unsigned long ma4 interval// 1unsigned long steps per sRr second// ad9usta"le feed factor for online tuning printer speed// volatile int feedmultiplH01::1 //1::8;original / ?:: 8; 'actor ? / E: 8; 'actor :.E 1int saved feedmultiplH 1volatile "ool feedmultiplHchanged0false volatile int e4trudemultiplH01::1 //1::8;1 ?::8;? 1"oolean acceleration ena"led 0 falseI accelerating 0 false// 1unsigned long interval// 15float destinationN(#- %<)SO 0 5:.:I :.:I :.:I :.: 15float current positionN(#- %<)SO 0 5:.:I :.:I :.:I :.: 15float add homingNAO05:I:I: 1static unsigned short virtual steps 4 0 : 1static unsigned short virtual steps H 0 : 1static unsigned short virtual steps J 0 : 1"ool home all a4is 0 true unsigned TT To+o7 Chec!// 1int feedrate 0 1E::I ne4t feedrateI saved feedrate 1long gcode (I gcode /ast( "ool relative mode 0 false1 //+etermines %"solute or &elative Coordinates 1Nunsigned long steps ta!enN(#- %<)S// long a4is intervalN(#- %<)SO1 // for speed delaH// 1float time for move// "ool relative mode e 0 false1 //+etermines %"solute or &elative $ Codes while in // .%"solute Coordinates mode. $ is alwaHs relative in &elative Coordinates mode 1long timediff 0 :// 1"ool is homing 0 false e4perimental feedrate calc// 1float d 0 ://

15float a4is diffN(#- %<)SO 0 5:I :I :I :// ifdef #S$ %&C '#(CT)*(# 'or arc center point coordinatesI sent "H commands .?/.A// 15float offsetNAO 0 5:.:I :.:I :.: endif# ifdef ST$, +$/%= &%T)*# 1long long step delaH ratio 0 ST$, +$/%= &%T)* U 1:: endif# oscillation reduction/// ifdef &%,)+ *SC)//%T)*( &$+#CT)*(# 15float cumm wait time in dirN(#- %<)SO05:.:I:.:I:.:I:.: 15"ool prev move directionN(#- %<)SO051I1I1I1 1float osc wait remainder 0 :.: endif# 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 1unsigned char fan last speed 0 : 1unsigned char fan org start speed 0 : 1unsigned long previous millis fan start 0 : endif# comm varia"les and Command"uffer // V#'S)>$ is reduced from B to F to free more &%- for the ,/%(($& // define -%< C-+ S)>$ DF# define V#'S)>$ F //B# 1Nchar cmd"ufferNV#'S)>$ON-%< C-+ S)>$ 1N"ool fromsdNV#'S)>$ (eed 1!" &am 88; onlH wor! with %tmega1?B4 // ifdef S+ '%ST <'$& %QT)M# 1Nchar fast4fer"ufferNS+ '%ST <'$& CC#(Q S)>$ W 1 1int last4ferchar 1long 4fer"Htes endif# 1unsigned char "ufindr 0 : 1unsigned char "ufindw 0 : 1unsigned char "uflen 0 : 1char serial char 1int serial count 0 : 1"oolean comment mode 0 false char Ustrchr pointer1 // 9ust a pointer to find chars in the cmd string li!e <I =I >I $I etc Send Temperature in XC to Cost// 1int hotendtC 0 :I "edtempC 0 :

)nactivitH shutdown varia"les// 1unsigned long previous millis cmd 0 : 1unsigned long ma4 inactive time 0 : 1unsigned long stepper inactive time 0 : Temp -onitor for repetier// 1unsigned char manage monitor 0 ?EE 888888888888888888888888888888888888888888888888// )nit the S+ card// 888888888888888888888888888888888888888888888888// ifdef S+S#,,*&T# 1Sd?Card card 1SdMolume volume 1Sd'ile root 1Sd'ile file 1uintA? t filesiJe 0 : 1uintA? t sdpos 0 : 1"ool sdmode 0 false 1"ool sdactive 0 false 1"ool savetosd 0 false 1int1F t read char int 23void initsd 6 1sdactive 0 false if S+SS ;8 1# 223if2root.is*pen 123root.close 622if 2Ycard.init2S,) '#// S,$$+IS+SS 22if 2Ycard.init2S,) C%/' S,$$+IS+SS// 122"showString2,ST&2"S+ init failZrZn 5 22else if 2Yvolume.init2[card 122"showString2,ST&2"volume.init failedZrZn 22else if 2Yroot.open&oot2[volume 122"showString2,ST&2"open&oot failedZrZn 6else 1sdactive 0 true 123print dis! info ifdef S+)()T')/$# 123file.close 622if2file.open2[rootI "init.g"I * &$%+ 1sdpos 0 : 123filesiJe 0 file.fileSiJe 1sdmode 0 true

5 endif# 5 endif# 5 ifdef S+ '%ST <'$& %QT)M# ifdef ,)+T$-,# 1e4tern volatile unsigned char g heater pwm val endif# 23void fast 4fer 6 1char Upstr 1"oolean done 0 false force heater pins low// 12if2C$%T$& : ,)( ; 813 @&)T$2C$%T$& : ,)(I/*@ 12if2C$%T$& 1 ,)( ; 813 @&)T$2C$%T$& 1 ,)(I/*@ ifdef ,)+T$-,# 1g heater pwm val 0 : endif# 1last4ferchar 0 1 14fer"Htes 0 : 12" " Ipstr 0 strstr2strchr pointerW4 2if2pstr 00 (#// 6 122"showString2,ST&2"invalid commandZrZn 1return 5 1Lpstr 0 LZ:U chec! mode 2currentlH onlH &%@ is supported// 2if2strcmp2strchr pointerW4I "&%@"3 Y0 : 6 122"showString2,ST&2")nvalid transfer codecZrZn 1return 6else5 122" 7showString2,ST&2"Selected codec 12Serial.println2strchr pointerW4 5 22if 2Yfile.open2[rootI pstrW1I * C&$%T \ * %,,$(+ \ * @&)T$ \ * T&#(C

6 122" 7showString2,ST&2"open failedI 'ile 12Serial.print2pstrW1 122"."3showString2,ST& 6else5 122" 7showString2,ST&2"@riting to file 12Serial.println2pstrW1 5 122"showString2,ST&2"o!ZrZn &%@ transfer codec// Cost sends Z: then up to S+ '%ST <'$& CC#(Q S)>$ then Z: // .when host is doneI it sends Z:Z:// if a non Z: character is recieved at the "eginningI host has failed somehowI !ill the// .transfer 2read S+ '%ST <'$& CC#(Q S)>$ "Htes 2or until Z: is recieved // 2while2Ydone 6 223while2YSerial.availa"le 6 5 2if2Serial.read23 Y0 : 6 host has failedI this isnLt a &%@ chun!I itLs an actual command // 123file.sHnc 123file.close 1return 5 2WWfor2int i0:1i<S+ '%ST <'$& CC#(Q S)>$W11i 6 223while2YSerial.availa"le 6 5 123last4ferchar 0 Serial.read ..."uffer the data// 1fast4fer"ufferNiO 0 last4ferchar 1WW4fer"Htes 2if2last4ferchar 00 : 1"rea! 5 2if2fast4fer"ufferN:O Y0 : 6 1fast4fer"ufferNS+ '%ST <'$& CC#(Q S)>$O 0 : 12file.write2fast4fer"uffer

122"showString2,ST&2"o!ZrZn 6else5 122" showString2,ST&2"@rote 12Serial.print24fer"Htes 122"showString2,ST&2" "Htes.ZrZn 1done 0 true 5 5 123file.sHnc 123file.close 5 endif# 2void print dis! info2void 6 print the tHpe of card // 122" 7showString2,ST&2"ZnCard tHpe 223switch2card.tHpe 6 7case S+ C%&+ T=,$ S+1 122"showString2,ST&2"S+1ZrZn 1"rea! 7case S+ C%&+ T=,$ S+? 122"showString2,ST&2"S+?ZrZn 1"rea! 7case S+ C%&+ T=,$ S+CC 122"showString2,ST&2"S+CCZrZn 1"rea! 7default 122"showString2,ST&2"#n!nownZrZn 5 1uintF4 t freeSpace 0 volume.clusterCount23Uvolume."loc!s,erCluster23UE1? // 1uintF4 t occupiedSpace 0 2card.cardSiJe23UE1?3 8 freeSpace// print the tHpe and siJe of the first '%T8tHpe volume // 1uintA? t volumesiJe 122"showString2,ST&2"ZnMolume tHpe is '%T 12Serial.println2volume.fatTHpe23I +$C volumesiJe 0 volume."loc!s,erCluster231 // clusters are collections of "loc!s volumesiJe U0 volume.clusterCount231 // weLll have a lot of clusters volumesiJe U0 E1?1 // S+ card "loc!s are alwaHs E1? "Htes volumesiJe /0 1:?41 //!"Htes volumesiJe /0 1:?41 //-"Htes 122" 72showString2,ST&2"Molume siJe 2-"Htes 12Serial.println2volumesiJe

list all files in the card with date and siJe // 12root.ls2/S & \ /S +%T$ \ /S S)>$// 5

2'*&C$ )(/)($ void write command2char U"uf 6 1charU "egin 0 "uf 1charU npos 0 : 1charU end 0 "uf W strlen2"uf3 8 1 1file.write$rror 0 false 2if22npos 0 strchr2"ufI L(L33 Y0 (#// 6 1"egin 0 strchr2nposI L L3 W 1 1end 0 strchr2nposI LUL3 8 1 5 1LendN1O 0 LZr 1LendN?O 0 LZn 1LendNAO 0 LZ: 12Serial.println2"egin// 12file.write2"egin 2if 2file.write$rror 6 122"showString2,ST&2"error writing to fileZrZn 5 5 endif# 2int 'ree&am12void 6 1e4tern int "ss end 1e4tern intU "r!val 1int free memorH 2if 2reinterpret cast<int;2 "r!val3 00 : 6 if no heap use from end of "ss section // free memorH 0 reinterpret cast<int;2[free memorH3 8 12reinterpret cast<int;2[ "ss end 5

else 6 use from top of stac! to heap // free memorH 0 reinterpret cast<int;2[free memorH3 8 12reinterpret cast<int;2 "r!val 5 1return free memorH 5 888888888888888888888888888888888888888888888888// 'unction the chec! the %nalog *#T pin for not using the Timer1 // 888888888888888888888888888888888888888888888888// 2void analog@rite chec!2uintB t chec! pinI int val 6 2 if defined2 %M& %Tmega1FB 3 \\ defined2 %M& %TmegaA?B,# %tmega1FB/A?B canLt use *C&1% and *C&1V// These are pins ,V1/,V? or on %rduino +D/+1:// 22if22chec! pin Y0 D3 [[ 2chec! pin Y0 1: 6 12analog@rite2chec! pinI val 5 endif# 2 if defined2 %M& %TmegaF44, 3 \\ defined2 %M& %Tmega1?B4,# %tmegaFF4,/1?B4, canLt use *C&1% and *C&1V// These are pins ,+4/,+E or on %rduino +1?/+1A// 22if22chec! pin Y0 1?3 [[ 2chec! pin Y0 1A 6 12analog@rite2chec! pinI val 5 endif# 2 if defined2 %M& %Tmega1?B: 3 \\ defined2 %M& %Tmega?EF:# %tmega1?B:/?EF: canLt use *C&1%I *C&1V and *C&1C// These are pins ,VEI,VFI,VG or on %rduino +11I+1? and +1A// 22if22chec! pin Y0 113 [[ 2chec! pin Y0 1?3 [[ 2chec! pin Y0 1A 6 12analog@rite2chec! pinI val 5 endif# 5 888888888888888888888888888888888888888888888888// 2,rint a String from 'lash to Serial 2save &%- // 888888888888888888888888888888888888888888888888// 2void showString 2,.- , s 6 1char c

2while 22c 0 pgm read "Hte2sWW33 Y0 : 12Serial.print2c 5 888888888888888888888888888888888888888888888888// )nit // 888888888888888888888888888888888888888888888888// 23void setup 6 12Serial."egin2V%#+&%T$ 122"showString2,ST&2"SprinterZrZn 122showString2,ST&2 M$&S)*( T$<T 122"showString2,ST&2"ZrZn 122"showString2,ST&2"startZrZn 2WWfor2int i 0 :1 i < V#'S)>$1 i 6 1fromsdNiO 0 false 5

)nitialiJe +ir ,ins// if < +)& ,)( ; 81# 12S$T *#T,#T2< +)& endif# if = +)& ,)( ; 81# 12S$T *#T,#T2= +)& endif# if > +)& ,)( ; 81# 12S$T *#T,#T2> +)& endif# if $ +)& ,)( ; 81# 12S$T *#T,#T2$ +)& endif#

,)( ,)( ,)( ,)(

.)nitialiJe $na"le ,ins 8 steppers default to disa"led // 2if 2< $(%V/$ ,)( ; 81# 12S$T *#T,#T2< $(%V/$ ,)( 12if2Y< $(%V/$ *(3 @&)T$2< $(%V/$ ,)(IC).C endif# 2if 2= $(%V/$ ,)( ; 81# 12S$T *#T,#T2= $(%V/$ ,)( 12if2Y= $(%V/$ *(3 @&)T$2= $(%V/$ ,)(IC).C endif# 2if 2> $(%V/$ ,)( ; 81# 12S$T *#T,#T2> $(%V/$ ,)(

12if2Y> $(%V/$ *(3 @&)T$2> $(%V/$ ,)(IC).C endif# 2if 2$ $(%V/$ ,)( ; 81# 12S$T *#T,#T2$ $(%V/$ ,)( 12if2Y$ $(%V/$ *(3 @&)T$2$ $(%V/$ ,)(IC).C endif# ifdef C*(T&*//$&'%( ,)(# S$T *#T,#T2C*(T&*//$&'%( ,)(31 //Set pin used for driver cooling fan endif# ifdef $<T&#+$&'%( ,)(# S$T *#T,#T2$<T&#+$&'%( ,)(31 //Set pin used for e4truder cooling fan endif# endstops and pullups// ifdef $(+ST*,,#//#,S# if < -)( ,)( ; 81# 12S$T )(,#T2< -)( ,)( 12@&)T$2< -)( ,)(IC).C endif# if < -%< ,)( ; 81# 12S$T )(,#T2< -%< ,)( 12@&)T$2< -%< ,)(IC).C endif# if = -)( ,)( ; 81# 12S$T )(,#T2= -)( ,)( 12@&)T$2= -)( ,)(IC).C endif# if = -%< ,)( ; 81# 12S$T )(,#T2= -%< ,)( 12@&)T$2= -%< ,)(IC).C endif# if > -)( ,)( ; 81# 12S$T )(,#T2> -)( ,)( 12@&)T$2> -)( ,)(IC).C endif# if > -%< ,)( ; 81# 12S$T )(,#T2> -%< ,)( 12@&)T$2> -%< ,)(IC).C endif# else# if < -)( ,)( ; 81# 12S$T )(,#T2< -)( ,)( endif# if < -%< ,)( ; 81# 12S$T )(,#T2< -%< ,)( endif# if = -)( ,)( ; 81# 12S$T )(,#T2= -)( ,)(

endif# if = -%< ,)( ; 81# 12S$T )(,#T2= -%< ,)( endif# if > -)( ,)( ; 81# 12S$T )(,#T2> -)( ,)( endif# if > -%< ,)( ; 81# 12S$T )(,#T2> -%< ,)( endif# endif# 2if 2C$%T$& : ,)( ; 81# 12S$T *#T,#T2C$%T$& : ,)( 12@&)T$2C$%T$& : ,)(I/*@ endif# 2if 2C$%T$& 1 ,)( ; 81# 12S$T *#T,#T2C$%T$& 1 ,)( 12@&)T$2C$%T$& 1 ,)(I/*@ endif# )nitialiJe 'an ,in// 2if 2'%( ,)( ; 81# 12S$T *#T,#T2'%( ,)( endif# )nitialiJe %larm ,in// 2if 2%/%&- ,)( ; 81# 12S$T *#T,#T2%/%&- ,)( 12@&)T$2%/%&- ,)(I/*@ endif# )nitialiJe /$+ ,in// 2if 2/$+ ,)( ; 81# 12S$T *#T,#T2/$+ ,)( 12@&)T$2/$+ ,)(I/*@ endif# )nitialiJe Step ,ins// 2if 2< ST$, ,)( ; 81# 12S$T *#T,#T2< ST$, endif# 2if 2= ST$, ,)( ; 81# 12S$T *#T,#T2= ST$, endif# 2if 2> ST$, ,)( ; 81# 12S$T *#T,#T2> ST$, endif# 2if 2$ ST$, ,)( ; 81# 12S$T *#T,#T2$ ST$,

,)( ,)( ,)( ,)(

endif#

62WWfor2int i0:1 i < (#- %<)S1 i // a4is ma4 intervalNiO 0 1::::::::.: / 2ma4 start speed units per secondNiO U // 12Na4is steps per unitNi a4is steps per sRr secondNiO 0 ma4 acceleration units per sR secondNiO U // 1Na4is steps per unitNi a4is travel steps per sRr secondNiO 0 // 1Nma4 travel acceleration units per sR secondNiO U a4is steps per unitNi 5 // ifdef C$%T$& #S$S -%<FFGE# 12S$T *#T,#T2SCQ ,)( 12@&)T$2SCQ ,)(I: 12S$T *#T,#T2-*S) ,)( 12@&)T$2-*S) ,)(I1 12S$T )(,#T2-)S* ,)( 12@&)T$2-)S* ,)(I1 12S$T *#T,#T2-%<FFGE SS 12@&)T$2-%<FFGE SSI1 endif# ifdef S+S#,,*&T# power to S+ reader// if S+,*@$& ; 81# 12S$T *#T,#T2S+,*@$& 12@&)T$2S+,*@$&IC).C endif# 122"showString2,ST&2"S+ StartZrZn 123initsd endif# if defined2,)+ S*'T ,@-3 \\ 2defined2'%( S*'T ,@-3 [[ 2'%( ,)( ; # 2281 122"showString2,ST&2"Soft ,@- )nitZrZn 123init Timer? softpwm endif# 122"showString2,ST&2",lanner )nitZrZn 1plan init231 // )nitialiJe planner 122"showString2,ST&2"Stepper Timer initZrZn

st init231

// )nitialiJe stepper

ifdef #S$ $$,&*- S$TT)(.S# first Malue 88; )nit with default// second value 88; ,rint settings to #%&T// 12$$,&*- &etrieveSettings2falseIfalse endif# ifdef ,)+T$-,# 123update,)+ endif# 'ree &am// 122" 7showString2,ST&2"'ree &am 1223Serial.println2'ree&am1 ,lanner Vuffer SiJe// 122"7showString2,ST&2",lan Vuffer SiJe 12Serial.print22int3siJeof2"loc! t3UV/*CQ V#''$& S)>$ 122" / "3showString2,ST& 12Serial.println2V/*CQ V#''$& S)>$ 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 a4is steps per sRr secondNiO 0 ma4 acceleration units per sR secondNiO U 1Na4is steps per unitNi 5 5

888888888888888888888888888888888888888888888888// -%)( /**,// 888888888888888888888888888888888888888888888888// 23void loop 6 22if2"uflen < 2V#'S)>$81 123get command 2if2"uflen 6 ifdef S+S#,,*&T# 2if2savetosd 6 2if2strstr2cmd"ufferN"ufindrOI"-?D"3 00 (#// 6 12Nwrite command2cmd"ufferN"ufindr 122"showString2,ST&2"o!ZrZn 5

else 6 123file.sHnc 123file.close 1savetosd 0 false 122"showString2,ST&2"+one saving file.ZrZn 5 5 else 6 123process commands 5 else# 123process commands endif# 12"uflen 0 2"uflen81 1"ufindr 0 2"ufindr W 13]V#'S)>$// &emoved modulo 2]3 operatorI which uses an e4pensive divide and // multiplication 1WW"ufindr 1if2"ufindr 00 V#'S)>$3 "ufindr 0 : 5 chec! heater everH n milliseconds// 123manage heater 12manage inactivitH21 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 123manage fan start speed endif# 5 888888888888888888888888888888888888888888888888// Chec! #art "uffer while arc function ist calc a circle // 888888888888888888888888888888888888888888888888// 23void chec! "uffer while arc 6 22if2"uflen < 2V#'S)>$81 6 123get command 5 5 888888888888888888888888888888888888888888888888// &$%+ C*--%(+ '&*- #%&T// 888888888888888888888888888888888888888888888888// 23void get command 6

2while2 Serial.availa"le23 ; : [[ "uflen < V#'S)>$ 6 123serial char 0 Serial.read if2serial char 00 LZnL \\ serial char 00 LZrL \\ 2serial char 00 L7L [[ comment mode 2 200 false3 \\ serial count ;0 2-%< C-+ S)>$ 8 1 6 if2Yserial count3 5 //if emptH line comment mode 0 false1 // for new command 1return 5 cmd"ufferN"ufindwONserial countO 0 :1 //terminate string 1fromsdN"ufindwO 0 false 2if2strstr2cmd"ufferN"ufindwOI "("3 Y0 (#// 6 12Lstrchr pointer 0 strchr2cmd"ufferN"ufindwOI L( gcode ( 0 2strtol2[cmd"ufferN"ufindwONstrchr pointer 8 cmd"ufferN"ufindwO W 1221OI (#//I 1: if2gcode ( Y0 gcode /ast(W1 [[ 2strstr2cmd"ufferN"ufindwOI "-11:"3 00 2 2(#// 6 showString2,ST&2"Serial $rror7 /ine (um"er is not /ast /ine (um"erW1I 122"7/ast /ine 12Serial.println2gcode /ast( 12Serial.println2gcode (// 123'lushSerial&eRuest&esend 1serial count 0 : 1return 5 2if2strstr2cmd"ufferN"ufindwOI "U"3 Y0 (#// 6 1"Hte chec!sum 0 : 1"Hte count 0 : while2cmd"ufferN"ufindwONcountO Y0 LUL3 chec!sum 0 1NWWchec!sumKcmd"ufferN"ufindwONcount 12LUL INstrchr pointer 0 strchr2cmd"ufferN"ufindw if2 2int32strtod2[cmd"ufferN"ufindwONstrchr pointer 8 cmd"ufferN"ufindwO W 21OI (#//33 Y0 chec!sum 6 122"7showString2,ST&2"$rror7 chec!sum mismatchI /ast /ine 12Serial.println2gcode /ast( 123'lushSerial&eRuest&esend 1serial count 0 : 1return 5 if no errorsI continue parsing// 5 else

6 122"7showString2,ST&2"$rror7 (o Chec!sum with line num"erI /ast /ine 12Serial.println2gcode /ast( 123'lushSerial&eRuest&esend 1serial count 0 : 1return 5 1gcode /ast( 0 gcode ( if no errorsI continue parsing// 5 LUL else // if we donLt receive L(L "ut still see 6 22if22strstr2cmd"ufferN"ufindwOI "U"3 Y0 (#// 6 122"7showString2,ST&2"$rror7 (o /ine (um"er with chec!sumI /ast /ine 12Serial.println2gcode /ast( 1serial count 0 : 1return 5 5 22if22strstr2cmd"ufferN"ufindwOI "."3 Y0 (#// 6 12Lstrchr pointer 0 strchr2cmd"ufferN"ufindwOI L. switch22int322strtod2[cmd"ufferN"ufindwONstrchr pointer 8 cmd"ufferN"ufindwO 2222W 1OI (#// 6 7case : 7case 1 ifdef #S$ %&C '#(CT)*(# case ?7 //.? case A7 //.A arc func endif# ifdef S+S#,,*&T# 2if2savetosd 1"rea! endif# 122"showString2,ST&2"o!ZrZn 12"Serial.println2"o!// 1"rea! 7default 1"rea! 5 5 &emoved modulo 2]3 operatorI which uses an e4pensive divide and // multiplication 1"ufindw 0 2"ufindw W 13]V#'S)>$// 1WW"ufindw

1if2"ufindw 00 V#'S)>$3 "ufindw 0 : 1"uflen W0 1 comment mode 0 false1 //for new command serial count 0 :1 //clear "uffer 5 else 6 1if2serial char 00 L1L3 comment mode 0 true 1if2Ycomment mode3 cmd"ufferN"ufindwONserial countWWO 0 serial char 5 5 ifdef S+S#,,*&T# 2if2Ysdmode \\ serial countY0: 6 1return 5 2while2 filesiJe ; sdpos [[ "uflen < V#'S)>$ 6 123serial char 0 file.read 1read char int 0 2int3serial char if2serial char 00 LZnL \\ serial char 00 LZrL \\ 2serial char 00 L7L [[ comment mode 200 false3 \\ serial count ;0 2-%< C-+ S)>$ 8 13 \\ read char int 00 81 6 123sdpos 0 file.cur,osition 2if2sdpos ;0 filesiJe 6 1sdmode 0 false 122"showString2,ST&2"+one printing fileZrZn 5 if2Yserial count3 5 //if emptH line comment mode 0 false1 // for new command 1return 5 cmd"ufferN"ufindwONserial countO 0 :1 //terminate string 1fromsdN"ufindwO 0 true 1"uflen W0 1 &emoved modulo 2]3 operatorI which uses an e4pensive divide and // multiplication 1"ufindw 0 2"ufindw W 13]V#'S)>$// 1WW"ufindw 1if2"ufindw 00 V#'S)>$3 "ufindw 0 : comment mode 0 false1 //for new command serial count 0 :1 //clear "uffer 5

else 6 1if2serial char 00 L1L3 comment mode 0 true 1if2Ycomment mode3 cmd"ufferN"ufindwONserial countWWO 0 serial char 5 5 endif# 5 1static "ool chec! endstops 0 true 2void ena"le endstops2"ool chec! 6 1chec! endstops 0 chec! 5 '*&C$ )(/)($ float code value23 5 return 2strtod2[cmd"ufferN"ufindrO 5 122Nstrchr pointer 8 cmd"ufferN"ufindrO W 1OI (#// '*&C$ )(/)($ long code value long23 5 return 2strtol2[cmd"ufferN"ufindrO 5 122Nstrchr pointer 8 cmd"ufferN"ufindrO W 1OI (#//I 1: '*&C$ )(/)($ "ool code seen2char code stringNO3 5 return 2strstr2cmd"ufferN"ufindrOI code string3 Y0 (#//31 6 //&eturn True if the string was found 2'*&C$ )(/)($ "ool code seen2char code 6 12strchr pointer 0 strchr2cmd"ufferN"ufindrOI code return 2strchr pointer Y0 (#//31 //&eturn True if a character was found 5 2'*&C$ )(/)($ void homing routine2char a4is 6 1int min pinI ma4 pinI home dirI ma4 lengthI home "ounce 62switch2a4is 7case < %<)S 1min pin 0 < -)( ,)( 1ma4 pin 0 < -%< ,)( 1home dir 0 < C*-$ +)& 1ma4 length 0 < -%< /$(.TC 1home "ounce 0 1: 1"rea! 7case = %<)S 1min pin 0 = -)( ,)( 1ma4 pin 0 = -%< ,)( 1home dir 0 = C*-$ +)& 1ma4 length 0 = -%< /$(.TC 1home "ounce 0 1: 1"rea!

7case > %<)S 1min pin 0 > -)( ,)( 1ma4 pin 0 > -%< ,)( 1home dir 0 > C*-$ +)& 1ma4 length 0 > -%< /$(.TC 1home "ounce 0 4 1"rea! 7default never reached// 1"rea! 5 22if 22min pin ; 81 [[ home dir00813 \\ 2ma4 pin ; 81 [[ home dir001 6 1current positionNa4isO 0 81.E U ma4 length U home dir plan set position2current positionN< %<)SOI current positionN= %<)SOI 12Ncurrent positionN> %<)SOI current positionN$ %<)S 1destinationNa4isO 0 : 1Nfeedrate 0 homing feedrateNa4is 123prepare move 123st sHnchroniJe 1current positionNa4isO 0 home "ounce/? U home dir plan set position2current positionN< %<)SOI current positionN= %<)SOI 12Ncurrent positionN> %<)SOI current positionN$ %<)S 1destinationNa4isO 0 : 123prepare move 123st sHnchroniJe 1current positionNa4isO 0 8home "ounce U home dir plan set position2current positionN< %<)SOI current positionN= %<)SOI 12Ncurrent positionN> %<)SOI current positionN$ %<)S 1destinationNa4isO 0 : 1feedrate 0 homing feedrateNa4isO/? 123prepare move 123st sHnchroniJe 1current positionNa4isO 0 2home dir 00 813 T : 7 ma4 length 1Ncurrent positionNa4isO W0 add homingNa4is plan set position2current positionN< %<)SOI current positionN= %<)SOI 12Ncurrent positionN> %<)SOI current positionN$ %<)S 1NdestinationNa4isO 0 current positionNa4is 1feedrate 0 : 5 5 888888888888888888888888888888888888888888888888// CC$CQ C*--%(+ %(+ C*(M$&T M%/#$S // 888888888888888888888888888888888888888888888888// 23'*&C$ )(/)($ void process commands

6 unsigned long codenum1 //throw awaH varia"le 1char Ustarpos 0 (#// 22Lif2code seen2L. 6 223switch22int3code value 6 case :7 // .: 8; .1 case 17 // .1 if 2defined +)S%V/$ CC$CQ +#&)(. %CC3 \\ 2defined # +)S%V/$ CC$CQ +#&)(. -*M$3 \\ 2defined 2+)S%V/$ CC$CQ +#&)(. T&%M$/ 123manage heater endif# get coordinates231 // 'or < = > $ ' 123prepare move 123previous millis cmd 0 millis 123ClearToSend// 1return 1"rea!// ifdef #S$ %&C '#(CT)*(# case ?7 // .? 8 C@ %&C 123get arc coordinates 12prepare arc move2true 123previous millis cmd 0 millis 1"rea!// 1return case A7 // .A 8 CC@ %&C 123get arc coordinates 12prepare arc move2false 123previous millis cmd 0 millis 1"rea!// 1return endif# case 47 // .4 dwell 1codenum 0 : if2code seen2L,L33 codenum 0 code value231 // milliseconds to wait if2code seen2LSL33 codenum 0 code value23 U 1:::1 // seconds to wait codenum W0 millis231 // !eep trac! of when we started waiting st sHnchroniJe231 // wait for all movements to finish 62 while2millis23 < codenum 123manage heater 5 1"rea! case ?B7 //.?B Come all %4is one at a time 1saved feedrate 0 feedrate 1saved feedmultiplH 0 feedmultiplH 123previous millis cmd 0 millis

1feedmultiplH 0 1:: 12ena"le endstops2true 2WWfor2int i0:1 i < (#- %<)S1 i 6 1NdestinationNiO 0 current positionNi 5 1feedrate 0 : 1is homing 0 true home all a4is 0 Y22code seen2a4is codesN:O33 \\ 2code seen2a4is codesN1O33 \\ 1222N2code seen2a4is codesN? 222Nif22home all a4is3 \\ 2code seen2a4is codesN< %<)S 12homing routine2< %<)S 222Nif22home all a4is3 \\ 2code seen2a4is codesN= %<)S 12homing routine2= %<)S 222Nif22home all a4is3 \\ 2code seen2a4is codesN> %<)S 12homing routine2> %<)S ifdef $(+ST*,S *(/= '*& C*-)(.# 12ena"le endstops2false endif# 1is homing 0 false 1feedrate 0 saved feedrate 1feedmultiplH 0 saved feedmultiplH 123previous millis cmd 0 millis 1"rea! case D:7 // .D: 1relative mode 0 false 1"rea! case D17 // .D1 1relative mode 0 true 1"rea! case D?7 // .D? 22Nif2Ycode seen2a4is codesN$ %<)S 123st sHnchroniJe 2WWfor2int i0:1 i < (#- %<)S1 i 6 123if2code seen2a4is codesNiO33 current positionNiO 0 code value 5 plan set position2current positionN< %<)SOI current positionN= %<)SOI 12Ncurrent positionN> %<)SOI current positionN$ %<)S 1"rea!

7default ifdef S$(+ @&*(. C-+ )('*# 122"7showString2,ST&2"#n!nown .8C*12NSerial.println2cmd"ufferN"ufindr endif# 1"rea! 5 5 22Lelse if2code seen2L6 2 23switch2 2int3code value 6 ifdef S+S#,,*&T# case ?:7 // -?: 8 list S+ card 122"showString2,ST&2"Vegin file listZrZn 123root.ls 122"showString2,ST&2"$nd file listZrZn 1"rea! case ?17 // -?1 8 init S+ card 1sdmode 0 false 123initsd 1"rea! case ??7 //-?? 8 release S+ card 1sdmode 0 false 1sdactive 0 false 1"rea! case ?A7 //-?A 8 Select file 2if2sdactive 6 1sdmode 0 false 123file.close 122LULIstarpos 0 2strchr2strchr pointer W 4 2if2starposY0(#// 1Lstarpos8130LZ:3U 22if 2file.open2[rootI strchr pointer W 4I * &$%+ 6 122"7showString2,ST&2"'ile opened 12Serial.print2strchr pointer W 4 122"7showString2,ST&2" SiJe 1223Serial.println2file.fileSiJe 1sdpos 0 : 123filesiJe 0 file.fileSiJe 122"showString2,ST&2"'ile selectedZrZn 5 else

6 122"showString2,ST&2"file.open failedZrZn 5 5 1"rea! case ?47 //-?4 8 Start S+ print 2if2sdactive 6 1sdmode 0 true 5 1"rea! case ?E7 //-?E 8 ,ause S+ print 2if2sdmode 6 1sdmode 0 false 5 1"rea! case ?F7 //-?F 8 Set S+ inde4 22Lif2sdactive [[ code seen2LS 6 123sdpos 0 code value long 12file.see!Set2sdpos 5 1"rea! case ?G7 //-?G 8 .et S+ status 2if2sdactive 6 122" showString2,ST&2"S+ printing "Hte 12Serial.print2sdpos 122"/"3showString2,ST& 12Serial.println2filesiJe 5 else 6 122"showString2,ST&2"(ot S+ printingZrZn 5 1"rea! case ?B7 //-?B 8 Start S+ write 2if2sdactive 6 1charU npos 0 : 123file.close 1sdmode 0 false 122LULIstarpos 0 2strchr2strchr pointer W 4 2if2starpos Y0 (#// 6 12Lnpos 0 strchr2cmd"ufferN"ufindrOI L( 1strchr pointer 0 strchr2nposIL L3 W 1 1Lstarpos813 0 LZ:3U 5

if 2Yfile.open2[rootI strchr pointerW4I * C&$%T \ * %,,$(+ \ * @&)T$ \ 22* T&#(C 6 122" 7showString2,ST&2"open failedI 'ile 12Serial.print2strchr pointer W 4 122"."3showString2,ST& 5 else 6 1savetosd 0 true 122" 7showString2,ST&2"@riting to file 12Serial.println2strchr pointer W 4 5 5 1"rea! case ?D7 //-?D 8 Stop S+ write processed in write to file routine a"ove// 1savetosd 0 false// 1"rea! ifndef S+ '%ST <'$& %QT)M# case A:7 // -A: filename 8 +elete file 2if2sdactive 6 1sdmode 0 false 123file.close 122LULIstarpos 0 2strchr2strchr pointer W 4 2if2starposY0(#// 1Lstarpos8130LZ:3U 22if2file.remove2[rootI strchr pointer W 4 6 122"showString2,ST&2"'ile deletedZrZn 5 else 6 122"showString2,ST&2"+eletion failedZrZn 5 5 1"rea! else# case A:7 //-A: 8 fast S+ transfer 123fast 4fer 1"rea! case A17 //-A1 8 high speed 4fer capa"ilities 122"7showString2,ST&2"&%@ 12Serial.println2S+ '%ST <'$& CC#(Q S)>$ 1"rea!

endif# endif# case 4?7 //-4? 8Change pin status via gcode 22Lif 2code seen2LS 6 ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# 123int pin status 0 code value 2if 2code seen2L,L3 [[ pin status ;0 : [[ pin status <0 ?EE 6 123int pin num"er 0 code value 2WWfor2int i 0 :1 i < siJeof2sensitive pins3 / siJeof2int31 i 6 2if 2sensitive pinsNiO 00 pin num"er 6 1pin num"er 0 81 1"rea! 5 5 2if 2pin num"er ; 81 6 12pin-ode2pin num"erI *#T,#T 12digital@rite2pin num"erI pin status 12analog@rite2pin num"erI pin status// 5 5 5 1"rea! case 1:47 // -1:4 ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# 1223if 2code seen2LSL33 target raw 0 temp?analogh2target temp 0 code value ifdef @%TCC,$&)*+# 2if2target raw ; current raw 6 1223watchmillis 0 ma421Imillis 1watch raw 0 current raw 5 else 6 1watchmillis 0 : 5 endif# 1"rea! case 14:7 // -14: set "ed temp ifdef CC%)( *' C*--%(+#

st sHnchroniJe231 // wait for all movements to finish endif# if T$-, 1 ,)( ; 81 \\ defined V$+ #S$S %+EDE# 1223if 2code seen2LSL33 target "ed raw 0 temp?analogVed2code value endif# 1"rea! case 1:E7 // -1:E if 2T$-, : ,)( ; 813 \\ defined 2C$%T$& #S$S -%<FFGE3\\ defined # C$%T$& #S$S %+EDE 12hotendtC 0 analog?temp2current raw endif# if T$-, 1 ,)( ; 81 \\ defined V$+ #S$S %+EDE# 12"edtempC 0 analog?tempVed2current "ed raw endif# if 2T$-, : ,)( ; 813 \\ defined 2C$%T$& #S$S -%<FFGE3 \\ defined # C$%T$& #S$S %+EDE 122"7showString2,ST&2"o! T 12Serial.print2hotendtC ifdef ,)+T$-,# 122"7^ "3showString2,ST& 12Serial.print2heater dutH U/ 122"7showString2,ST&2"I, 12Serial.print2pTerm 122"7showString2,ST&2"I) 12Serial.print2iTerm 122"7showString2,ST&2"I+ 12Serial.print2dTerm /U ifdef %#T*T$-,# 122"7showString2,ST&2"I%# 12Serial.print2autotemp setpoint endif# endif# if T$-, 1 ,)( ; 81 \\ defined V$+ #S$S %+EDE# 122"7showString2,ST&2" V 12Serial.println2"edtempC else# 123Serial.println endif# else# error (o temperature source availa"le# endif# 1return 1"rea!// .case 1:D7 5 // -1:D 8 @ait for e4truder heater to reach target ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# 1223if 2code seen2LSL33 target raw 0 temp?analogh2target temp 0 code value

ifdef @%TCC,$&)*+# 2if2target raw;current raw 6 1223watchmillis 0 ma421Imillis 1watch raw 0 current raw 5 else 6 1watchmillis 0 : 5 endif# 123codenum 0 millis /U See if we are heating up or cooling down U/ "ool target direction 0 2current raw < target raw31 // true if heatingI false if cooling ifdef T$-, &$S)+$(C= T)-$# 1long residencHStart 1residencHStart 0 81 continue to loop until we have reached the target temp U/ /U and until T$-, &$S)+$(C= T)-$ hasnLt passed since we reached it while2 2target direction T 2current raw < target raw3 7 2current raw ; 22target raw residencHStart ; 81 [[ 2millis23 8 residencHStart3 < 3 \\ 6 2 2T$-, &$S)+$(C= T)-$U1::: else# while 2 target direction T 2current raw < target raw3 7 2current raw ; 6 2 2target raw endif# if2 2millis23 8 codenum3 ; 1::: 3 //,rint Temp &eading everH 1 second while heating up/cooling down 6 122"7showString2,ST&2"T 12 2Serial.println2 analog?temp2current raw 123codenum 0 millis 5 123manage heater 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 123manage fan start speed endif# ifdef T$-, &$S)+$(C= T)-$# start/restart the T$-, &$S)+$(C= T)-$ timer whenever we reach U/ target temp for the first time or when current temp falls outside the hHsteresis after target temp was /U reached if 2 2residencHStart 00 81 [[ target direction [[ current raw ;0 2target raw residencHStart 00 81 [[ Ytarget direction [[ current raw <0 3 \\ 2target raw

residencHStart ; 81 [[ la"s2analog?temp2current raw3 8 3 \\ 6 2 2analog?temp2target raw33 ; T$-, C=ST$&$S)S 123residencHStart 0 millis 5 endif# 5 5 1"rea! .case 1D:7 // -1D: 8 @ait for "ed heater to reach target temperature ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# if T$-, 1 ,)( ; 81# 1223if 2code seen2LSL33 target "ed raw 0 temp?analogVed2code value 123codenum 0 millis 2while2current "ed raw < target "ed raw 6 if2 2millis238codenum3 ; 1::: 3 //,rint Temp &eading everH 1 second while .heating up 6 12hotendtC0analog?temp2current raw 122"7showString2,ST&2"T 12 Serial.print2 hotendtC 122"7showString2,ST&2" V 12 2Serial.println2 analog?tempVed2current "ed raw 123codenum 0 millis 5 123manage heater 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 123manage fan start speed endif# 5 endif# 1"rea! if '%( ,)( ; 81# case 1:F7 //-1:F 'an *n ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# 22Lif 2code seen2LS 6 12unsigned char l fan code val 0 constrain2code value23I:I?EE 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 2if2l fan code val ; : [[ fan last speed 00 : 6 2if2l fan code val < -)()-#- '%( ST%&T S,$$+ 6 1fan org start speed 0 l fan code val 1l fan code val 0 -)()-#- '%( ST%&T S,$$+

123previous millis fan start 0 millis 5 1fan last speed 0 l fan code val 5 else 6 1fan last speed 0 l fan code val 1fan org start speed 0 : 5 endif# 2if defined2'%( S*'T ,@-3 [[ 2'%( ,)( ; 81# 1g fan pwm val 0 l fan code val else# 12@&)T$2'%( ,)(I C).C 1analog@rite chec!2'%( ,)(I l fan code val endif# 5 else 6 2if defined2'%( S*'T ,@-3 [[ 2'%( ,)( ; 81# 1g fan pwm val 0 ?EE else# 12@&)T$2'%( ,)(I C).C 12 analog@rite chec!2'%( ,)(I ?EE endif# 5 1"rea! case 1:G7 //-1:G 'an *ff 2if defined2'%( S*'T ,@-3 [[ 2'%( ,)( ; 81# 1g fan pwm val 0 : else# 12analog@rite chec!2'%( ,)(I : 12@&)T$2'%( ,)(I /*@ endif# 1"rea! endif# 2if 2,S *( ,)( ; 81# case B:7 // -B1 8 %T< ,ower *n S$T *#T,#T2,S *( ,)(31 //.(+ 1"rea! case B17 // -B1 8 %T< ,ower *ff ifdef CC%)( *' C*--%(+# st sHnchroniJe231 // wait for all movements to finish endif# S$T )(,#T2,S *( ,)(31 //'loating 1"rea! endif# 7case B?

1a4is relative modesNAO 0 false 1"rea! 7case BA 1a4is relative modesNAO 0 true 1"rea! 7case B4 st sHnchroniJe231 // wait for all movements to finish 22Lif2code seen2LS 6 1stepper inactive time 0 code value23 U 1::: 5 22Lelse if2code seen2LT 6 123ena"le 4 123ena"le H 123ena"le J 123ena"le e 5 else 6 123disa"le 4 123disa"le H 123disa"le J 123disa"le e 5 1"rea! case BE7 // -BE 12Lcode seen2LS 1ma4 inactive time 0 code value23 U 1::: 1"rea! case D?7 // -D? 2WWfor2int i0:1 i < (#- %<)S1 i 6 22Nif2code seen2a4is codesNi 6 123a4is steps per unitNiO 0 code value a4is steps per sRr secondNiO 0 ma4 acceleration units per sR secondNiO U 1Na4is steps per unitNi 5 5 #pdate start speed intervals and a4is order. T*+*7 refactor // a4is ma4 intervalNO calculation into a functionI as it should also "e used in setup23 as well // 1Nlong temp ma4 intervalsN(#- %<)S // 2WWfor2int i0:1 i < (#- %<)S1 i // 6 // a4is ma4 intervalNiO 0 1::::::::.: / 2ma4 start speed units per secondNiO U a4is steps per unitNiO31//T*+*7 do this for all steps per unit related varia"les //

//

5 // 1"rea! .case DA7 // -DA show current a4is steps 122" showString2,ST&2"o! 122"7showString2,ST&2"< 12NSerial.print2a4is steps per unitN: 122"7showString2,ST&2"= 12NSerial.print2a4is steps per unitN1 122"7showString2,ST&2"> 12NSerial.print2a4is steps per unitN? 122"7showString2,ST&2"$ 12NSerial.println2a4is steps per unitNA 1"rea! case 11E7 // -11E showString2,ST&2"')&-@%&$ (%-$7 Sprinter $4perimental ,&*T*C*/ M$&S)*(71.: -%CC)($ T=,$7-endel 122"$<T&#+$& C*#(T71ZrZn 12Serial.println2uuid// 122showString2,ST&2 +$' CC%& ##)+ 122"showString2,ST&2"ZrZn 1"rea! case 1147 // -114 122"7showString2,ST&2"< 12NSerial.print2current positionN: 122"7showString2,ST&2"= 12NSerial.print2current positionN1 122"7showString2,ST&2"> 12NSerial.print2current positionN? 122"7showString2,ST&2"$ 12NSerial.println2current positionNA 1"rea! case 11D7 // -11D 2if 2< -)( ,)( ; 81# 122"7showString2,ST&2"4 12" Serial.print22&$%+2< endif# 2if 2< -%< ,)( ; 81# 122"7showString2,ST&2"4 12" Serial.print22&$%+2< endif# 2if 2= -)( ,)( ; 81# 122"7showString2,ST&2"H 12" Serial.print22&$%+2= endif# 2if 2= -%< ,)( ; 81# 122"7showString2,ST&2"H 12" Serial.print22&$%+2= endif# 2if 2> -)( ,)( ; 81# min -)( ,)(3K< $(+ST*, )(M$&T3T"C "7"/ ma4 -%< ,)(3K< $(+ST*, )(M$&T3T"C "7"/ min -)( ,)(3K= $(+ST*, )(M$&T3T"C "7"/ ma4 -%< ,)(3K= $(+ST*, )(M$&T3T"C "7"/

122"7showString2,ST&2"J 12" Serial.print22&$%+2> endif# 2if 2> -%< ,)( ; 81# 122"7showString2,ST&2"J 12" Serial.print22&$%+2> endif#

min -)( ,)(3K> $(+ST*, )(M$&T3T"C "7"/ ma4 -%< ,)(3K> $(+ST*, )(M$&T3T"C "7"/

122"showString2,ST&2"ZrZn 1"rea! case ?:17 // -?:1 Set ma4imum acceleration in units/sK? for print moves 2-?:1 2<1::: =1::: 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 22Nif2code seen2a4is codesNi 6 123ma4 acceleration units per sR secondNiO 0 code value 1Na4is steps per sRr secondNiO 0 code value23 U a4is steps per unitNi 5 5 1"rea! if : // (ot used for Sprinter/gr"l genF# case ?:?7 // -?:? 2WWfor2int i0:1 i < (#- %<)S1 i 6 if2code seen2a4is codesNiO33 a4is travel steps per sRr secondNiO 0 1Ncode value23 U a4is steps per unitNi 5 1"rea! else# case ?:?7 // -?:? ma4 feedrate mm/sec 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 123if2code seen2a4is codesNiO33 ma4 feedrateNiO 0 code value 5 1"rea! endif# case ?:A7 // -?:A Temperature monitor 123if2code seen2LSL33 manage monitor 0 code value if2manage monitor001::3 manage monitor011 // Set 1:: to heated "ed 1"rea! case ?:47 // -?:4 acceleration S normal moves T filmanent onlH moves 1 23if2code seen2LSL33 move acceleration 0 code value 1 23if2code seen2LTL33 retract acceleration 0 code value 1"rea! case ?:E7 //-?:E advanced settings7 minimum travel speed S0while printing T0travel onlHI V0minimum segment time <0 ma4imum 4H 9er!I >0ma4imum > 9er!I $0 ma4 $ 9er! 123if2code seen2LSL33 minimumfeedrate 0 code value

123if2code seen2LTL33 mintravelfeedrate 0 code value 1 23if2code seen2LVL33 minsegmenttime 0 code value// 1 23if2code seen2L<L33 ma4 4H 9er! 0 code value 1 23if2code seen2L>L33 ma4 J 9er! 0 code value 1 23if2code seen2L$L33 ma4 e 9er! 0 code value 1"rea! case ?:F7 // -?:F additional homing offset 22Lif2code seen2L+ 6 12NshowString2,ST&2"%ddhome <7"331 Serial.print2add homingN: 12NshowString2,ST&2" =7"331 Serial.print2add homingN1 12NshowString2,ST&2" >7"331 Serial.println2add homingN? 5 2WWfor2intB t cnt i0:1 cnt i < A1 cnt i 6 123if2code seen2a4is codesNcnt iO33 add homingNcnt iO 0 code value 5 1"rea! case ??:7 // -??: S<factor in percent;8 set speed factor override percentage 6 22Lif2code seen2LS 6 1 23feedmultiplH 0 code value 12feedmultiplH 0 constrain2feedmultiplHI ?:I ?:: 1feedmultiplHchanged0true 5 5 1"rea! case ??17 // -??1 S<factor in percent;8 set e4trude factor override percentage 6 22Lif2code seen2LS 6 1 23e4trudemultiplH 0 code value 12e4trudemultiplH 0 constrain2e4trudemultiplHI 4:I ?:: 5 5 1"rea! ifdef ,)+T$-,# case A:17 // -A:1 6 123if2code seen2L,L33 ,)+ Qp 0 code value 123if2code seen2L)L33 ,)+ Qi 0 code value 123if2code seen2L+L33 ,)+ Qd 0 code value 123update,)+ 5 1"rea! endif //,)+T$-,# ifdef ,)+ %#T*T#($# case A:A7 // -A:A ,)+ autotune

6 1float help temp 0 1E:.: 123if 2code seen2LSL33 help temp0code value 12,)+ autotune2help temp 5 1"rea! endif# case 4::7 // -4:: finish all moves 6 123st sHnchroniJe 5 1"rea! ifdef #S$ $$,&*- S$TT)(.S# case E::7 // Store settings in $$,&*6 123$$,&*- StoreSettings 5 1"rea! case E:17 // &ead settings from $$,&*6 12$$,&*- &etrieveSettings2falseItrue 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 a4is steps per sRr secondNiO 0 ma4 acceleration units per sR secondNiO U 1Na4is steps per unitNi 5 5 1"rea! case E:?7 // &evert to default settings 6 12$$,&*- &etrieveSettings2trueItrue 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 a4is steps per sRr secondNiO 0 ma4 acceleration units per sR secondNiO U 1Na4is steps per unitNi 5 5 1"rea! case E:A7 // print settings currentlH in memorH 6 123$$,&*- printSettings 5 1"rea! endif# ifdef +$V#. C$%T$& T$-,# case F:17 // -F:1 show $4truder Temp 9itter if 2T$-, : ,)( ; 813 \\ defined 2C$%T$& #S$S -%<FFGE3\\ defined # C$%T$& #S$S %+EDE 2if2current raw ma4val ; : 12tt ma4val 0 analog?temp2current raw ma4val

2if2current raw minval < 1:::: 12tt minval 0 analog?temp2current raw minval endif# 122"7showString2,ST&2"Tmin 12Serial.print2tt minval 122"7showString2,ST&2" / Tma4 12Serial.print2tt ma4val 122" "3showString2,ST& 1"rea! case F:?7 // -F:? reset $4truder Temp 9itter 1current raw minval 0 A?::: 1current raw ma4val 0 8A?::: 122" showString2,ST&2"T -inma4 &eset 1"rea! endif# case F:A7 // -F:A 'ree &%122" 7showString2,ST&2"'ree &am 1223Serial.println2'ree&am1 1"rea! 7default ifdef S$(+ @&*(. C-+ )('*# 122"7showString2,ST&2"#n!nown -8C*12NSerial.println2cmd"ufferN"ufindr endif# 1"rea! 5 5 6else 122"showString2,ST&2"#n!nown command7ZrZn 12NSerial.println2cmd"ufferN"ufindr 5 123ClearToSend 5

23void 'lushSerial&eRuest&esend 6 1"7char cmd"ufferN"ufindrON1::O0"&esend// 123Serial.flush 122"7showString2,ST&2"&esend 12Serial.println2gcode /ast( W 1 123ClearToSend 5

23void ClearToSend 6 123previous millis cmd 0 millis ifdef S+S#,,*&T# 2Nif2fromsdN"ufindr 1return endif# 122"showString2,ST&2"o!ZrZn 12"Serial.println2"o!// 5 23'*&C$ )(/)($ void get coordinates 6 2WWfor2int i0:1 i < (#- %<)S1 i 6 if2code seen2a4is codesNiO33 destinationNiO 0 2float3code value23 W 1N2a4is relative modesNiO \\ relative mode3Ucurrent positionNi else destinationNiO 0 current positionNiO1 Tthese else lines reallH needed 5 22Lif2code seen2L' 6 123ne4t feedrate 0 code value 1if2ne4t feedrate ; :.:3 feedrate 0 ne4t feedrate 5 5 ifdef #S$ %&C '#(CT)*(# 23void get arc coordinates 6 123get coordinates 6 22Lif2code seen2L) 123offsetN:O 0 code value 5 6 else 1offsetN:O 0 :.: 5 6 22Lif2code seen2LP 123offsetN1O 0 code value 5 6 else 1offsetN1O 0 :.: 5 5 endif#

//%re

23void prepare move 6 1long help feedrate 0 : 62if2Yis homing 2if 2min software endstops 6 1if 2destinationN< %<)SO < :3 destinationN< %<)SO 0 :.: 1if 2destinationN= %<)SO < :3 destinationN= %<)SO 0 :.: 1if 2destinationN> %<)SO < :3 destinationN> %<)SO 0 :.: 5 2if 2ma4 software endstops 6 if 2destinationN< %<)SO ; < -%< /$(.TC3 destinationN< %<)SO 0 1< -%< /$(.TC if 2destinationN= %<)SO ; = -%< /$(.TC3 destinationN= %<)SO 0 1= -%< /$(.TC if 2destinationN> %<)SO ; > -%< /$(.TC3 destinationN> %<)SO 0 1> -%< /$(.TC 5 5 2Nif2destinationN$ %<)SO ; current positionN$ %<)S 6 12help feedrate 0 22long3feedrateU2long3feedmultiplH 5 else 6 12help feedrate 0 22long3feedrateU2long31:: 5 plan "uffer line2destinationN< %<)SOI destinationN= %<)SOI destinationN> %<)SOI 12destinationN$ %<)SOI help feedrate/F:::.: 2WWfor2int i0:1 i < (#- %<)S1 i 6 1Ncurrent positionNiO 0 destinationNi 5 5 ifdef #S$ %&C '#(CT)*(# 2void prepare arc move2char iscloc!wise 6 float r 0 hHpot2offsetN< %<)SOI offsetN= %<)SO31 // Compute arc radius for mc arc 1long help feedrate 0 : 2Nif2destinationN$ %<)SO ; current positionN$ %<)S

6 12help feedrate 0 22long3feedrateU2long3feedmultiplH 5 else 6 12help feedrate 0 22long3feedrateU2long31:: 5 Trace the arc // mc arc2current positionI destinationI offsetI < %<)SI = %<)SI > %<)SI 12help feedrate/F:::.:I rI iscloc!wise %s far as the parser is concernedI the position is now 00 target. )n realitH the // motion control sHstem might still "e processing the action and the real tool // position .in anH intermediate location // 2WWfor2intB t i0:1 i < (#- %<)S1 i 6 1Ncurrent positionNiO 0 destinationNi 5 5 endif# 23'*&C$ )(/)($ void !ill 6 if T$-, : ,)( ; 81# 1target raw0: 12@&)T$2C$%T$& : ,)(I/*@ endif# if T$-, 1 ,)( ; 81# 1target "ed raw0: 12if2C$%T$& 1 ,)( ; 813 @&)T$2C$%T$& 1 ,)(I/*@ endif# 123disa"le 123disa"le 123disa"le 123disa"le 4 H J e

12if2,S *( ,)( ; 813 pin-ode2,S *( ,)(I)(,#T 5 2'*&C$ )(/)($ void manage inactivitH2"Hte de"ug 6 if2 2millis238previous millis cmd3 ; ma4 inactive time 3 if2ma4 inactive time3 123!ill

if2 2millis238previous millis cmd3 ; stepper inactive time 3 2if2stepper inactive time 6 123disa"le 4 123disa"le H 123disa"le J 123disa"le e 5 123chec! a4es activitH 5 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 2void manage fan start speed2void 6 2if2fan org start speed ; : 6 2 if22millis23 8 previous millis fan start3 ; -)()-#- '%( ST%&T T)-$ 6 if '%( ,)( ; 81# 2if defined2'%( S*'T ,@-# 1g fan pwm val 0 fan org start speed else# 12@&)T$2'%( ,)(I C).C 1analog@rite chec!2'%( ,)(I fan org start speed endif# endif# 1fan org start speed 0 : 5 5 5 endif# ,lanner with )nterrupt for Stepper // U/ 72L&easoning "ehind the mathematics in this module 2in the !eH of L-athematica s 00 speedI a 00 accelerationI t 00 timeI d 00 distance 7Vasic definitions 2SpeedNs I a I t O 70 s W 2aUt NTravelNs I a I t O 70 )ntegrateNSpeedNsI aI tOI t 7+istance to reach a specific speed with a constant acceleration NSolveN5SpeedNsI aI tO 00 mI TravelNsI aI tO 00 d6I dI t 23d 8; 2mK? 8 sK?3/2? a3 88; estimate acceleration distance

7Speed after a given distance of travel with constant acceleration NSolveN5SpeedNsI aI tO 00 mI TravelNsI aI tO 00 d6I mI t Nm 8; SRrtN? a d W sK? N+estinationSpeedNs I a I d O 70 SRrtN? a d W sK? @hen to start "ra!ing 2di3 to reach a specified destionation speed 2s?3 after accelerating 7from initial speed s1 without ever stopping at a plateau NSolveN5+estinationSpeedNs1I aI diO 00 +estinationSpeedNs?I aI d 8 diO6I di 23di 8; 2? a d 8 s1K? W s?K?3/24 a3 88; intersection distance 2)ntersection+istanceNs1 I s? I a I d O 70 2? a d 8 s1K? W s?K?3/24 a /U static "loc! t "loc! "ufferNV/*CQ V#''$& S)>$O1 // % ring "uffer for motion instructions static volatile unsigned char "loc! "uffer head1 // )nde4 of the ne4t "loc! to "e pushed static volatile unsigned char "loc! "uffer tail1 // )nde4 of the "loc! to process now 000000000000000000000000000000000000000000000000000000000000// 000000000000000 private varia"les00000000000000000000000000000// 0000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000// 000000000000000 &eturns the inde4 of the ne4t "loc! in the ring "uffer // (*T$7 &emoved modulo 2]3 operatorI which uses an e4pensive divide and // .multiplication 6 2static intB t ne4t "loc! inde42intB t "loc! inde4 1WW"loc! inde4 5 1if 2"loc! inde4 00 V/*CQ V#''$& S)>$3 5 "loc! inde4 0 : 12return2"loc! inde4 5 &eturns the inde4 of the previous "loc! in the ring "uffer // 6 2static intB t prev "loc! inde42intB t "loc! inde4 5 1if 2"loc! inde4 00 :3 5 "loc! inde4 0 V/*CQ V#''$& S)>$ 188"loc! inde4 12return2"loc! inde4 5

The current position of the tool in a"solute steps // 1Nstatic long positionN4 static float previous speedN4O1 // Speed of previous path line segment static float previous nominal speed1 // (ominal speed of previous path line segment 1static unsigned char .D? reset previous speed 0 : Calculates the distance 2not time3 it ta!es to accelerate from initial rate to // target rate using the 7given acceleration // '*&C$ )(/)($ float estimate acceleration distance2float initial rateI float 2target rateI float acceleration 6 6 2if 2accelerationY0: /2return22target rateUtarget rate8initial rateUinitial rate 122accelerationU?.:3 5 6 else return :.:1 // acceleration was :I set acceleration distance to : 5 5 This function gives Hou the point at which Hou must start "ra!ing 2at the rate of // 8acceleration3 if Hou started at speed initial rate and accelerated until this point and want to end at // the final rate after a total travel of distance. This can "e used to compute the intersection point "etween // acceleration and deceleration in the cases where the trapeJoid has no plateau 2i.e. never reaches // 2ma4imum speed '*&C$ )(/)($ float intersection distance2float initial rateI float final rateI float 2accelerationI float distance 6 6 2if 2accelerationY0: /2return22?.:UaccelerationUdistance8initial rateUinitial rateWfinal rateUfinal rate 12 2accelerationU4.:3 5 6 else return :.:1 // acceleration was :I set intersection distance to : 5 5 Calculates trapeJoid parameters so that the entrH8 and e4it8speed is compensated "H // .the provided factors void calculate trapeJoid for "loc!2"loc! t U"loc!I float entrH factorI float 6 2e4it factor 2unsigned long initial rate 0 ceil2"loc!8;nominal rateUentrH factor31 // 2step/min 2unsigned long final rate 0 ceil2"loc!8;nominal rateUe4it factor31 // 2step/min

2./imit minimal step rate 2*therwise the timer will overflow // 5 1if2initial rate <1?:3 5initial rate01?: 5 1if2final rate < 1?:3 5final rate01?: 1long acceleration 0 "loc!8;acceleration st 0 intA? t accelerate steps ceil2estimate acceleration distance2"loc!8;initial rateI "loc!8;nominal rateI 122acceleration 0 intA? t decelerate steps floor2estimate acceleration distance2"loc!8;nominal rateI "loc!8;final rateI 1228acceleration .Calculate the siJe of ,lateau of (ominal &ate // 1intA? t plateau steps 0 "loc!8;step event count8accelerate steps8decelerate steps )s the ,lateau of (ominal &ate smaller than nothingT That means no cruisingI and // we will have to use intersection distance23 to calculate when to a"ort acceleration and start // "rea!ing .in order to reach the final rate e4actlH at the end of this "loc! // 6 2if 2plateau steps < : 3accelerate steps 0 ceil intersection distance2"loc!8;initial rateI "loc!8;final rateI accelerationI "loc!8 122;step event count accelerate steps 0 ma42accelerate stepsI:31 // Chec! limits due to numerical round8 off 12accelerate steps 0 min2accelerate stepsI"loc!8;step event count 1plateau steps 0 : 5 ifdef %+M%(C$# 1volatile long initial advance 0 "loc!8;advanceUentrH factorUentrH factor 1volatile long final advance 0 "loc!8;advanceUe4it factorUe4it factor endif // %+M%(C$# 1"loc!8;accelerate until 0 accelerate steps // 1"loc!8;decelerate after 0 accelerate stepsWplateau steps // C&)T)C%/ S$CT)*( ST%&T1 // 'ill varia"les used "H the stepper in a critical section .if2"loc!8;"usH 00 false3 5 // +onLt update varia"les if "loc! is "usH 1"loc!8;accelerate until 0 accelerate steps 1"loc!8;decelerate after 0 accelerate stepsWplateau steps 1"loc!8;initial rate 0 initial rate 1"loc!8;final rate 0 final rate ifdef %+M%(C$# 1"loc!8;initial advance 0 initial advance 1"loc!8;final advance 0 final advance endif //%+M%(C$# 5

1C&)T)C%/ S$CT)*( $(+ 5 Calculates the ma4imum allowa"le speed at this point when Hou must "e a"le to // reach target velocitH using the .acceleration within the allotted distance // '*&C$ )(/)($ float ma4 allowa"le speed2float accelerationI float target velocitHI 6 2float distance 12return sRrt2target velocitHUtarget velocitH8?UaccelerationUdistance 5 Punction 9er!" in this conte4t is the immediate change in speed at the 9unction of " // .two "loc!s This method will calculate the 9unction 9er! as the euclidean distance "etween the // nominal .velocities of the respective "loc!s // 6 2inline float 9unction 9er!2"loc! t U"eforeI "loc! t Uafter // 3return sRrt // pow22"efore8;speed 48after8;speed 43I ?3Wpow22"efore8;speed H8after8 // 122;speed H3I ? 5//

The !ernel called "H planner recalculate23 when scanning the plan from last to first // .entrH 2void planner reverse pass !ernel2"loc! t UpreviousI "loc! t UcurrentI "loc! t Une4t 6 5 1if2Ycurrent3 5 return 6 2if 2ne4t )f entrH speed is alreadH at the ma4imum entrH speedI no need to rechec!. Vloc! // .is cruising )f notI "loc! in state of acceleration or deceleration. &eset entrH speed to // ma4imum and chec! for ma4imum allowa"le speed reductions to ensure ma4imum possi"le // .planned speed 6 2if 2current8;entrH speed Y0 current8;ma4 entrH speed )f nominal length trueI ma4 9unction speed is guaranteed to "e reached. *nlH // compute .for ma4 allowa"le speed if "loc! is decelerating and nominal length is false // if 22Ycurrent8;nominal length flag3 [[ 2current8;ma4 entrH speed ; ne4t8 6 22;entrH speed Icurrent8;entrH speed 0 min2 current8;ma4 entrH speed ma4 allowa"le speed28current8;accelerationIne4t8;entrH speedIcurrent8 122;millimeters 6 else 5 1current8;entrH speed 0 current8;ma4 entrH speed 5

1current8;recalculate flag 0 true 5 .S!ip last "loc!. %lreadH initialiJed and set for recalculation // 5 5 planner recalculate23 needs to go over the current plan twice. *nce in reverse and // once forward. This .implements the reverse pass // 6 23void planner reverse pass 1uintB t "loc! inde4 0 "loc! "uffer head -a!e a local copH of "loc! "uffer tailI "ecause the interrupt can alter it// 1C&)T)C%/ S$CT)*( ST%&T 1unsigned char tail 0 "loc! "uffer tail 1C&)T)C%/ S$CT)*( $(+ if222"loc! "uffer head8tail W V/*CQ V#''$& S)>$3 [ 22V/*CQ V#''$& S)>$ 8 133 ; A 6 12"loc! inde4 0 2"loc! "uffer head 8 A3 [ 2V/*CQ V#''$& S)>$ 8 1 15 "loc! t U"loc!NAO 0 5 (#//I (#//I (#// 6 2while2"loc! inde4 Y0 tail 12"loc! inde4 0 prev "loc! inde42"loc! inde4 1N"loc!N?O0 "loc!N1 1N"loc!N1O0 "loc!N: 1N"loc!N:O 0 ["loc! "ufferN"loc! inde4 12Nplanner reverse pass !ernel2"loc!N:OI "loc!N1OI "loc!N? 5 5 5 The !ernel called "H planner recalculate23 when scanning the plan from first to last // .entrH void planner forward pass !ernel2"loc! t UpreviousI "loc! t UcurrentI "loc! t 6 2Une4t 5 1if2Yprevious3 5 return )f the previous "loc! is an acceleration "loc!I "ut it is not long enough to complete // the full speed change within the "loc!I we need to ad9ust the entrH speed accordinglH. // $ntrH speeds have alreadH "een resetI ma4imiJedI and reverse planned "H reverse // .planner )f nominal length is trueI ma4 9unction speed is guaranteed to "e reached. (o need // .to rechec! 6 2if 2Yprevious8;nominal length flag 6 2if 2previous8;entrH speed < current8;entrH speed Idou"le entrH speed 0 min2 current8;entrH speed

ma4 allowa"le speed28previous8;accelerationIprevious8;entrH speedIprevious8 12 2;millimeters Chec! for 9unction speed change // 6 2if 2current8;entrH speed Y0 entrH speed 1current8;entrH speed 0 entrH speed 1current8;recalculate flag 0 true 5 5 5 5 planner recalculate23 needs to go over the current plan twice. *nce in reverse and // once forward. This .implements the forward pass // 6 23void planner forward pass 1uintB t "loc! inde4 0 "loc! "uffer tail 15 "loc! t U"loc!NAO 0 5 (#//I (#//I (#// 6 2while2"loc! inde4 Y0 "loc! "uffer head 1N"loc!N:O 0 "loc!N1 1N"loc!N1O 0 "loc!N? 1N"loc!N?O 0 ["loc! "ufferN"loc! inde4 12Nplanner forward pass !ernel2"loc!N:OI"loc!N1OI"loc!N? 12"loc! inde4 0 ne4t "loc! inde42"loc! inde4 5 12planner forward pass !ernel2"loc!N1OI "loc!N?OI (#// 5 &ecalculates the trapeJoid speed profiles for all "loc!s in the plan according to the // entrH factor for each 9unction. -ust "e called "H planner recalculate23 after // .updating the "loc!s // 6 23void planner recalculate trapeJoids 1intB t "loc! inde4 0 "loc! "uffer tail 1"loc! t Ucurrent 1"loc! t Une4t 0 (#// 6 2while2"loc! inde4 Y0 "loc! "uffer head 1current 0 ne4t 1Nne4t 0 ["loc! "ufferN"loc! inde4 6 2if 2current .&ecalculate if current "loc! entrH or e4it 9unction speed has changed // 6 2if 2current8;recalculate flag \\ ne4t8;recalculate flag .(*T$7 $ntrH and e4it factors alwaHs ; : "H all previous logic operations // calculate trapeJoid for "loc!2currentI current8;entrH speed/current8 I;nominal speed 12ne4t8;entrH speed/current8;nominal speed current8;recalculate flag 0 false1 // &eset current onlH to ensure ne4t trapeJoid is computed 5

5 12 "loc! inde4 0 ne4t "loc! inde42 "loc! inde4 5 /ast/newest "loc! in "uffer. $4it speed is set with // .-)()-#- ,/%(($& S,$$+. %lwaHs recalculated 6 2if2ne4t Y0 (#// Icalculate trapeJoid for "loc!2ne4tI ne4t8;entrH speed/ne4t8;nominal speed 12-)()-#- ,/%(($& S,$$+/ne4t8;nominal speed 1ne4t8;recalculate flag 0 false 5 5 7&ecalculates the motion plan according to the following algorithm // // .o over everH "loc! in reverse order and calculate a 9unction speed reduction .1 // 22i.e. "loc! t.entrH factor 7so that // a. The 9unction 9er! is within the set limit // ". (o speed reduction within one "loc! reRuires faster deceleration than the oneI // true constant .acceleration // .o over everH "loc! in chronological order and dial down 9unction speed .? // reduction values if a. The speed increase within one "loc! would reRuire faster accelleration than the // oneI true .constant acceleration // // @hen these stages are complete all "loc!s have an entrH factor that will allow all // speed changes to "e performed using onlH the oneI true constant accelerationI and where no 9unction // 9er! is 9er!ier than 7the set limit. 'inallH it will // // .&ecalculate trapeJoids for all "loc!s .A // 6 23void planner recalculate 123planner reverse pass 123planner forward pass 123planner recalculate trapeJoids 5 6 23void plan init 1"loc! "uffer head 0 : 1"loc! "uffer tail 0 : memset2positionI :I siJeof2position331 // clear position 1previous speedN:O 0 :.: 1previous speedN1O 0 :.: 1previous speedN?O 0 :.: 1previous speedNAO 0 :.: 1previous nominal speed 0 :.:

6 23'*&C$ )(/)($ void plan discard current "loc! 6 2if 2"loc! "uffer head Y0 "loc! "uffer tail 1"loc! "uffer tail 0 2"loc! "uffer tail W 13 [ V/*CQ V#''$& -%SQ 5 5 6 23'*&C$ )(/)($ "loc! t Uplan get current "loc! 6 2if 2"loc! "uffer head 00 "loc! "uffer tail 12return2(#// 5 1N"loc! t U"loc! 0 ["loc! "ufferN"loc! "uffer tail 1"loc!8;"usH 0 true 12return2"loc! 5 .ets the current "loc!. &eturns (#// if "uffer emptH // 23'*&C$ )(/)($ "ool "loc!s Rueued 6 6 2if 2"loc! "uffer head 00 "loc! "uffer tail 1return false 5 else 1return true 5 6 23void chec! a4es activitH 1unsigned char 4 active 0 : 1unsigned char H active 0 : 1unsigned char J active 0 : 1unsigned char e active 0 : 1"loc! t U"loc! 6 2if2"loc! "uffer tail Y0 "loc! "uffer head 1uintB t "loc! inde4 0 "loc! "uffer tail 6 2while2"loc! inde4 Y0 "loc! "uffer head 1N"loc! 0 ["loc! "ufferN"loc! inde4 1WWif2"loc!8;steps 4 Y0 :3 4 active 1WWif2"loc!8;steps H Y0 :3 H active 1WWif2"loc!8;steps J Y0 :3 J active 1WWif2"loc!8;steps e Y0 :3 e active 12"loc! inde4 0 2"loc! inde4W13 [ 2V/*CQ V#''$& S)>$ 8 1 5 5 123if22+)S%V/$ <3 [[ 24 active 00 :33 disa"le 4 123if22+)S%V/$ =3 [[ 2H active 00 :33 disa"le H 123if22+)S%V/$ >3 [[ 2J active 00 :33 disa"le J

123if22+)S%V/$ $3 [[ 2e active 00 :33 disa"le e 5 1float 9unction deviation 0 :.1 1float ma4 $ feedrate calc 0 -%< &$T&%CT '$$+&%T$ 1"ool retract feedrate a!tiv 0 false %dd a new linear movement to the "uffer. steps 4I H and J is the a"solute // position in mm. -icroseconds specifH how manH microseconds the move should ta!e to // perform. To aid acceleration calculation the caller must also provide the phHsical length of the line in // .millimeters 2void plan "uffer line2float 4I float HI float JI float eI float feed rate 6 Calculate the "uffer head after we push this "Hte // 12int ne4t "uffer head 0 ne4t "loc! inde42"loc! "uffer head .)f the "uffer is full7 goodY That means we are well ahead of the ro"ot // .&est here until there is room in the "uffer // 6 2while2"loc! "uffer tail 00 ne4t "uffer head 123manage heater 12manage inactivitH21 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 123manage fan start speed endif# 5 The target position of the tool in a"solute steps // Calculate target position in a"solute steps // this should "e done after the waitI "ecause otherwise a -D? code within the gcode // disrupts this calculation somehow 1Nlong targetN4 12NtargetN< %<)SO 0 lround24Ua4is steps per unitN< %<)S 12NtargetN= %<)SO 0 lround2HUa4is steps per unitN= %<)S 12NtargetN> %<)SO 0 lround2JUa4is steps per unitN> %<)S 12NtargetN$ %<)SO 0 lround2eUa4is steps per unitN$ %<)S ,repare to set up new "loc! // 1N"loc! t U"loc! 0 ["loc! "ufferN"loc! "uffer head 2-ar! "loc! as not "usH 2(ot e4ecuted "H the stepper interrupt // 1"loc!8;"usH 0 false (um"er of steps for each a4is // 12N"loc!8;steps 4 0 la"s2targetN< 12N"loc!8;steps H 0 la"s2targetN= 12N"loc!8;steps J 0 la"s2targetN> 12N"loc!8;steps e 0 la"s2targetN$ %<)SO8positionN< %<)S %<)SO8positionN= %<)S %<)SO8positionN> %<)S %<)SO8positionN$ %<)S

1"loc!8;steps e U0 e4trudemultiplH 1"loc!8;steps e /0 1:: "loc!8;step event count 0 ma42"loc!8;steps 4I ma42"loc!8;steps HI ma42"loc!8 1222;steps JI "loc!8;steps e Vail if this is a Jero8length "loc! // 15 1if 2"loc!8;step event count <0dropsegments3 5 return Compute direction "its for this "loc! // 1"loc!8;direction "its 0 : if 2targetN< %<)SO < positionN< %<)SO3 5 "loc!8;direction "its \0 5 1221<<< %<)S if 2targetN= %<)SO < positionN= %<)SO3 5 "loc!8;direction "its \0 5 1221<<= %<)S 5 12if 2targetN> %<)SO < positionN> %<)SO3 5 "loc!8;direction "its \0 21<<> %<)S 2Nif 2targetN$ %<)SO < positionN$ %<)S 6 12"loc!8;direction "its \0 21<<$ %<)S Cigh 'eedrate for retract// 1ma4 $ feedrate calc 0 -%< &$T&%CT '$$+&%T$ 1retract feedrate a!tiv 0 true 5 else 6 2if2retract feedrate a!tiv 6 2if2"loc!8;steps e ; : 1retract feedrate a!tiv 0 false 5 else 6 1Nma4 $ feedrate calc 0 ma4 feedrateN$ %<)S 5 5 ifdef +$/%= $(%V/$# 2if2"loc!8;steps 4 Y0 : 6 123ena"le 4 12delaH-icroseconds2+$/%= $(%V/$ 5 2if2"loc!8;steps H Y0 : 6 123ena"le H 12delaH-icroseconds2+$/%= $(%V/$ 5 2if2"loc!8;steps J Y0 : 6 123ena"le J

12delaH-icroseconds2+$/%= $(%V/$ 5 2if2"loc!8;steps e Y0 : 6 123ena"le e 12delaH-icroseconds2+$/%= $(%V/$ 5 else# ena"le active a4es// 123if2"loc!8;steps 4 Y0 :3 ena"le 4 123if2"loc!8;steps H Y0 :3 ena"le H 123if2"loc!8;steps J Y0 :3 ena"le J 123if2"loc!8;steps e Y0 :3 ena"le e endif# 6 2if 2"loc!8;steps e 00 : 1if2feed rate<mintravelfeedrate3 feed rate0mintravelfeedrate 5 6 else 1if2feed rate<minimumfeedrate3 feed rate0minimumfeedrate 5 slow down when the "uffer starts to emptHI rather than wait at the corner for a // "uffer refill int moves Rueued02"loc! "uffer head8"loc! "uffer tail W 12V/*CQ V#''$& S)>$3 [ 2V/*CQ V#''$& S)>$ 8 1 ifdef S/*@+*@(# if2moves Rueued < 2V/*CQ V#''$& S)>$ U :.E3 [[ moves Rueued ; 13 12feed rate 0 feed rateUmoves Rueued / 2V/*CQ V#''$& S)>$ U :.E endif# 1Nfloat delta mmN4 delta mmN< %<)SO 0 2targetN< %<)SO8 1NpositionN< %<)SO3/a4is steps per unitN< %<)S delta mmN= %<)SO 0 2targetN= %<)SO8 1NpositionN= %<)SO3/a4is steps per unitN= %<)S delta mmN> %<)SO 0 2targetN> %<)SO8 1NpositionN> %<)SO3/a4is steps per unitN> %<)S delta mmN$ %<)SO 0 2targetN$ %<)SO8// 1NpositionN$ %<)SO3/a4is steps per unitN$ %<)S delta mmN$ %<)SO 0 22targetN$ %<)SO8 1positionN$ %<)SO3/a4is steps per unitN$ %<)SO3Ue4trudemultiplH/1::.: if 2 "loc!8;steps 4 <0 dropsegments [[ "loc!8;steps H <0 dropsegments [[ 6 2 "loc!8;steps J <0 dropsegments 12N"loc!8;millimeters 0 fa"s2delta mmN$ %<)S 6 else 5 "loc!8;millimeters 0 sRrt2sRuare2delta mmN< %<)SO3 W 122NsRuare2delta mmN= %<)SO3 W sRuare2delta mmN> %<)S 5

float inverse millimeters 0 1.:/"loc!8;millimeters1 // )nverse millimeters to remove multiple divides Calculate speed in mm/second for each a4is. (o divide "H Jero due to previous // .chec!s 1float inverse second 0 feed rate U inverse millimeters "loc!8;nominal speed 0 "loc!8;millimeters U inverse second1 // 2mm/sec3 %lwaHs ;: "loc!8;nominal rate 0 ceil2"loc!8;step event count U inverse second31 // 2step/sec3 %lwaHs ; :

U/ segment time im micro seconds // 12long segment time 0 lround21::::::.:/inverse second 6 222if 22"loc!count;:3 [[ 2"loc!count < 2V/*CQ V#''$& S)>$ 8 4 if 2segment time<minsegmenttime3 5 // "uffer is drainingI add e4tra time. The .amount of time added increases if the "uffer is still emptied more segment time0segment timeWlround2?U2minsegmenttime8 12segment time3/"loc!count 5 5 6 else 1if 2segment time<minsegmenttime3 segment time0minsegmenttime 5 $(+ *' S/*@ +*@( S$CT)*( // /U Calculate and limit speed in mm/sec for each a4is // 1Nfloat current speedN4 float speed factor 0 1.:1 //factor <01 do decrease speed 2WWfor2int i0:1 i < A1 i 6 1current speedNiO 0 delta mmNiO U inverse second 2Nif2fa"s2current speedNiO3 ; ma4 feedrateNi 122Nspeed factor 0 min2speed factorI ma4 feedrateNiO / fa"s2current speedNi 5 1current speedN$ %<)SO 0 delta mmN$ %<)SO U inverse second 2if2fa"s2current speedN$ %<)SO3 ; ma4 $ feedrate calc speed factor 0 min2speed factorI ma4 $ feedrate calc / 122Nfa"s2current speedN$ %<)S

Correct the speed // 2if2 speed factor < 1.: 6 6 2WWfor2unsigned char i0:1 i < 41 i 1current speedNiO U0 speed factor 5 1"loc!8;nominal speed U0 speed factor 1"loc!8;nominal rate U0 speed factor 5 .Compute and limit the acceleration rate for the trapeJoid generator // 1float steps per mm 0 "loc!8;step event count/"loc!8;millimeters 6 2if2"loc!8;steps 4 00 : [[ "loc!8;steps H 00 : [[ "loc!8;steps J 00 : "loc!8;acceleration st 0 ceil2retract acceleration U steps per mm31 // convert to7 acceleration steps/secK? 5 6 else "loc!8;acceleration st 0 ceil2move acceleration U steps per mm31 // convert to7 acceleration steps/secK? /imit acceleration per a4is // if222float3"loc!8;acceleration st U 2float3"loc!8;steps 4 / 2float3"loc!8 2N;step event count3 ; a4is steps per sRr secondN< %<)S 1N"loc!8;acceleration st 0 a4is steps per sRr secondN< %<)S if222float3"loc!8;acceleration st U 2float3"loc!8;steps H / 2float3"loc!8 2N;step event count3 ; a4is steps per sRr secondN= %<)S 1N"loc!8;acceleration st 0 a4is steps per sRr secondN= %<)S if222float3"loc!8;acceleration st U 2float3"loc!8;steps e / 2float3"loc!8 2N;step event count3 ; a4is steps per sRr secondN$ %<)S 1N"loc!8;acceleration st 0 a4is steps per sRr secondN$ %<)S if222float3"loc!8;acceleration st U 2float3"loc!8;steps J / 2float3"loc!8 2N;step event count 3 ; a4is steps per sRr secondN> %<)S 1N"loc!8;acceleration st 0 a4is steps per sRr secondN> %<)S 5 1"loc!8;acceleration 0 "loc!8;acceleration st / steps per mm 12"loc!8;acceleration rate 0 2long322float3"loc!8;acceleration st U B.ABBF:B if : // #se old 9er! for now# Compute path unit vector // 1Ndou"le unit vecNA 1unit vecN< %<)SO 0 delta mmN< %<)SOUinverse millimeters 1unit vecN= %<)SO 0 delta mmN= %<)SOUinverse millimeters 1unit vecN> %<)SO 0 delta mmN> %<)SOUinverse millimeters Compute ma4imum allowa"le entrH speed at 9unction "H centripetal acceleration // .appro4imation /et a circle "e tangent to "oth previous and current path line segmentsI where the // 9unction deviation is defined as the distance from the 9unction to the closest edge of the // Icircle

colinear with the circle center. The circular segment 9oining the two paths // represents the path of centripetal acceleration. Solve for ma4 velocitH "ased on ma4 acceleration // a"out the radius of the circleI defined indirectlH "H 9unction deviation. This maH "e also // viewed as path width or ma4 9er! in the previous gr"l version. This approach does not // actuallH deviate from pathI "ut used as a ro"ust waH to compute cornering speedsI as it ta!es into // account the .nonlinearities of "oth the 9unction angle and 9unction velocitH // dou"le vma4 9unction 0 -)()-#- ,/%(($& S,$$+1 // Set default ma4 9unction speed S!ip first "loc! or when previous nominal speed is used as a flag for homing and // .offset cHcles 6 22if 22"loc! "uffer head Y0 "loc! "uffer tail3 [[ 2previous nominal speed ; :.: Compute cosine of angle "etween previous and current path. 2prev unit vec is // 2negative (*T$7 -a4 9unction velocitH is computed without sin23 or acos23 "H trig half // .angle identitH Ndou"le cos theta 0 8 previous unit vecN< %<)SO U unit vecN< %<)S Nprevious unit vecN= %<)SO U unit vecN= %<)S 8 1 Nprevious unit vecN> %<)SO U unit vecN> %<)S 8 .S!ip and use default ma4 9unction speed for : degree acute 9unction // 6 2if 2cos theta < :.DE 12vma4 9unction 0 min2previous nominal speedI"loc!8;nominal speed S!ip and avoid divide "H Jero for straight 9unctions at 1B: degrees. /imit to // .min23 of nominal speeds 6 2if 2cos theta ; 8:.DE Compute ma4imum 9unction velocitH "ased on ma4imum acceleration and // 9unction deviation dou"le sin theta d? 0 sRrt2:.EU21.:8cos theta331 // Trig half angle identitH. .%lwaHs positive Ivma4 9unction 0 min2vma4 9unction sRrt2"loc!8;acceleration U 9unction deviation U sin theta d?/21.:8 12 22sin theta d? 5 5 5 endif# Start with a safe speed // 1float vma4 9unction 0 ma4 4H 9er!/? 1float vma4 9unction factor 0 1.: 2if2fa"s2current speedN> %<)SO3 ; ma4 J 9er!/? 12vma4 9unction 0 min2vma4 9unctionI ma4 J 9er!/? 2if2fa"s2current speedN$ %<)SO3 ; ma4 e 9er!/?

12vma4 9unction 0 min2vma4 9unctionI ma4 e 9er!/? 2if2.D? reset previous speed 00 1 6 1vma4 9unction 0 :.1 1.D? reset previous speed 0 : 5 12vma4 9unction 0 min2vma4 9unctionI "loc!8;nominal speed 1float safe speed 0 vma4 9unction 6 22if 22moves Rueued ; 13 [[ 2previous nominal speed ; :.:::1 float 9er! 0 sRrt2pow22current speedN< %<)SO8previous speedN< %<)SO3I 122?3Wpow22current speedN= %<)SO8previous speedN= %<)SO3I ? if22fa"s2previous speedN< %<)SO3 ; :.:::13 \\ // 6 222fa"s2previous speedN= %<)SO3 ; :.:::1 1vma4 9unction 0 "loc!8;nominal speed 5 // 6 2if 29er! ; ma4 4H 9er! 12vma4 9unction factor 0 2ma4 4H 9er!/9er! 5 6 2if2fa"s2current speedN> %<)SO 8 previous speedN> %<)SO3 ; ma4 J 9er! vma4 9unction factor0 min2vma4 9unction factorI 1222N2ma4 J 9er!/fa"s2current speedN> %<)SO 8 previous speedN> %<)S 5 6 2if2fa"s2current speedN$ %<)SO 8 previous speedN$ %<)SO3 ; ma4 e 9er! vma4 9unction factor 0 min2vma4 9unction factorI 1222N2ma4 e 9er!/fa"s2current speedN$ %<)SO 8 previous speedN$ %<)S 5 vma4 9unction 0 min2previous nominal speedI vma4 9unction U vma4 9unction factor31 // /imit speed to ma4 previous speed 5 1"loc!8;ma4 entrH speed 0 vma4 9unction )nitialiJe "loc! entrH speed. Compute "ased on deceleration to user8defined // .-)()-#- ,/%(($& S,$$+ dou"le v allowa"le 0 ma4 allowa"le speed28"loc!8 12;accelerationI-)()-#- ,/%(($& S,$$+I"loc!8;millimeters 12"loc!8;entrH speed 0 min2vma4 9unctionI v allowa"le )nitialiJe planner efficiencH flags // Set flag if "loc! will alwaHs reach ma4imum 9unction speed regardless of // .entrH/e4it speeds )f a "loc! can de/ac8celerate from nominal speed to Jero within the length of the // "loc!I then the current "loc! and ne4t "loc! 9unction speeds are guaranteed to alwaHs "e at // their ma4imum 9unction speeds in deceleration and accelerationI respectivelH. This is due to how // the current

"loc! nominal speed limits "oth the current and ne4t ma4imum 9unction speeds. // CenceI in "oth the reverse and forward plannersI the corresponding "loc! 9unction speed will // alwaHs "e at the the ma4imum 9unction speed and maH alwaHs "e ignored for anH speed reduction // .chec!s 6 2if 2"loc!8;nominal speed <0 v allowa"le 1"loc!8;nominal length flag 0 true 5 6 else 1"loc!8;nominal length flag 0 false 5 "loc!8;recalculate flag 0 true1 // %lwaHs calculate trapeJoid for new "loc! #pdate previous path unit vector and nominal speed // memcpH2previous speedI current speedI siJeof2previous speed331 // NOprevious speedNO 0 current speed 1previous nominal speed 0 "loc!8;nominal speed ifdef %+M%(C$# Calculate advance rate // if22"loc!8;steps e 00 :3 \\ 2"loc!8;steps 4 00 : [[ "loc!8;steps H 00 : [[ 6 22"loc!8;steps J 00 : 1"loc!8;advance rate 0 : 1"loc!8;advance 0 : 5 6 else long acc dist 0 estimate acceleration distance2:I "loc!8;nominal rateI "loc!8 12;acceleration st U 2float advance 0 2ST$,S ,$& C#V)C -- $ U $<T&#+$& %+M%(C$ Q current speedN$ %<)SO U current speedN$ %<)SO U $<T&#T)*( %&$% U 3 1$<T&#T)*( %&$%3U?EF 1"loc!8;advance 0 advance 6 2if2acc dist 00 : 1"loc!8;advance rate 0 : 5 6 else 1"loc!8;advance rate 0 advance / 2float3acc dist 5 5 endif // %+M%(C$# Icalculate trapeJoid for "loc!2"loc!I "loc!8;entrH speed/"loc!8;nominal speed 12safe speed/"loc!8;nominal speed -ove "uffer head // 1"loc! "uffer head 0 ne4t "uffer head

#pdate position // NOmemcpH2positionI targetI siJeof2target331 // positionNO 0 target 123planner recalculate ifdef %#T*T$-,# 123getCigh$Speed endif# 123st wa!e up 5 2int calc plannerpuffer fill2void 6 int moves Rueued02"loc! "uffer head8"loc! "uffer tail W 12V/*CQ V#''$& S)>$3 [ 2V/*CQ V#''$& S)>$ 8 1 12return2moves Rueued 5 2void plan set position2float 4I float HI float JI float e 6 12NpositionN< %<)SO 0 lround24Ua4is steps per unitN< %<)S 12NpositionN= %<)SO 0 lround2HUa4is steps per unitN= %<)S 12NpositionN> %<)SO 0 lround2JUa4is steps per unitN> %<)S 12NpositionN$ %<)SO 0 lround2eUa4is steps per unitN$ %<)S 1virtual steps 4 0 : 1virtual steps H 0 : 1virtual steps J 0 : previous nominal speed 0 :.:1 // &esets planner 9unction speeds. %ssumes start .from rest 1previous speedN:O 0 :.: 1previous speedN1O 0 :.: 1previous speedN?O 0 :.: 1previous speedNAO 0 :.: 1.D? reset previous speed 0 1 5 ifdef %#T*T$-,# 23void getCigh$Speed 6 1static float oldt0: 2if2Yautotemp ena"led 1return .if22target tempW?3 < autotemp min3 //pro"a"lH temperature set to Jero return1 //do nothing 1float high0:.: 1uintB t "loc! inde4 0 "loc! "uffer tail

6 2while2"loc! inde4 Y0 "loc! "uffer head \\ 2if22"loc! "ufferN"loc! inde4O.steps 4 Y0 : \\ 2"loc! "ufferN"loc! inde4O.steps H Y0 :3 6 22"loc! "ufferN"loc! inde4O.steps J Y0 :3 float se02float2"loc! "ufferN"loc! inde4O.steps e3/float2"loc! "ufferN"loc! inde4O.step e 1vent count33U"loc! "ufferN"loc! inde4O.nominal speed 1se1 units steps/sec// 2if2se;high 6 1high0se 5 5 12"loc! inde4 0 2"loc! inde4W13 [ 2V/*CQ V#''$& S)>$ 8 1 5 1float t0autotemp minWhighUautotemp factor 2if2t<autotemp min 1t0autotemp min 2if2t;autotemp ma4 1t0autotemp ma4 2if2oldt;t 6 1t0%#T*T$-, */+@$).CTUoldtW218%#T*T$-, */+@$).CT3Ut 5 1oldt0t 1autotemp setpoint 0 2int3t 5 endif#

Stepper // int&es 0 int)n1 U int)n? ;; 1F // 7uses // r?F to store : // r?G to store the "Hte 1 of the ?4 "it result // Z 2define -ulti#1F<BtoC1F2int&esI char)n1I int)n?# Z 3 asm volatile Z "clr r?F ZnZt" Z "mul ]%1I ]V? ZnZt" Z "movw ]%:I r: ZnZt" Z "mul ]%1I ]%? ZnZt" Z "add ]%:I r1 ZnZt" Z "adc ]V:I r?F ZnZt"

Z "lsr r: ZnZt" Z "adc ]%:I r?F ZnZt" Z "adc ]V:I r?F ZnZt" Z "clr r1 ZnZt" Z7 Z 2r" 2int&es[0" Z7 Z I2d" 2char)n1" Z 2d" 2int)n?" Z7 Z "r?F" 2 int&es 0 long)n1 U long)n? ;; ?4 // 7uses // r?F to store : // r?G to store the "Hte 1 of the 4B"it result // Z 2define -ulti#?4<?4toC1F2int&esI long)n1I long)n?# Z 3 asm volatile Z "clr r?F ZnZt" Z "mul ]%1I ]V? ZnZt" Z "mov r?GI r1 ZnZt" Z "mul ]V1I ]C? ZnZt" Z "movw ]%:I r: ZnZt" Z "mul ]C1I ]C? ZnZt" Z "add ]V:I r: ZnZt" Z "mul ]C1I ]V? ZnZt" Z "add ]%:I r: ZnZt" Z "adc ]V:I r1 ZnZt" Z "mul ]%1I ]C? ZnZt" Z "add r?GI r: ZnZt" Z "adc ]%:I r1 ZnZt" Z "adc ]V:I r?F ZnZt" Z "mul ]V1I ]V? ZnZt" Z "add r?GI r: ZnZt" Z "adc ]%:I r1 ZnZt" Z "adc ]V:I r?F ZnZt" Z "mul ]C1I ]%? ZnZt" Z "add r?GI r: ZnZt" Z "adc ]%:I r1 ZnZt" Z "adc ]V:I r?F ZnZt" Z "mul ]V1I ]%? ZnZt" Z "add r?GI r1 ZnZt" Z "adc ]%:I r?F ZnZt" Z "adc ]V:I r?F ZnZt" Z "lsr r?G ZnZt" Z "adc ]%:I r?F ZnZt" Z "adc ]V:I r?F ZnZt" Z "clr r1 ZnZt" Z7

Z 2r" 2int&es[0" Z7 Z I2d" 2long)n1" Z 2d" 2long)n?" Z7 Z "r?F" I "r?G" 2 Some useful constants // 2define $(%V/$ ST$,,$& +&)M$& )(T$&&#,T23 T)-SQ1 \0 21<<*C)$1% # define +)S%V/$ ST$,,$& +&)M$& )(T$&&#,T23 T)-SQ1 [0 # 2_21<<*C)$1% ifdef $(+ST*,S *(/= '*& C*-)(.# 2define CC$CQ $(+ST*,S if2chec! endstops # else# define CC$CQ $(+ST*,S# endif# static "loc! t Ucurrent "loc!1 // % pointer to the "loc! currentlH "eing traced Maria"les used "H The Stepper +river )nterrupt // static unsigned char out "its1 // The ne4t stepping8"its to "e output static long counter 4I // Counter varia"les for the "resenham line tracer Icounter H Icounter J 1counter e static unsigned long step events completed1 // The num"er of step events e4ecuted in the current "loc! ifdef %+M%(C$# 1static long advance rateI advanceI final advance 0 : 1static short old advance 0 : endif# 1static short e steps static unsigned char "usH 0 false1 // T&#$ when S). *#T,#T C*-,%&$1% is ."eing serviced. #sed to avoid retriggering that handler 1static long acceleration timeI deceleration time static unsigned short acc step rate1 // needed for deceleration start point 1static char step loops 1static unsigned short *C&1% nominal 1static volatile "ool endstop 4 hit0false 1static volatile "ool endstop H hit0false 1static volatile "ool endstop J hit0false 1static "ool old 1static "ool old 1static "ool old 1static "ool old 4 4 H H min ma4 min ma4 endstop0false endstop0false endstop0false endstop0false

1static "ool old J min endstop0false 1static "ool old J ma4 endstop0false

// K Z\ \/ // \ Z\ \/ Z \ \/ // s Z\ \/Z \ \ / // p Z \ \ \ \ \ / // e Z \ \ \ \ \ / // e W8888W888888888888888W88W888W888888888888888888888888W88888W // V/*CQ 1 \ V/*CQ ? \ d \ // // <88888 time // // The trapeJoid is the shape of the speed curve over time. )t starts at "loc!8 // ;initial rateI accelerates first "loc!8;accelerate until step events completedI then !eeps going at constant // speed until step events completed reaches "loc!8;decelerate after after which it decelerates // .until the trapeJoid generator is reset .The slope of acceleration is calculated with the lei" ramp alghorithm // 23void st wa!e up 6 1TC(T1 0 : // 2if2"usH 00 false 123$(%V/$ ST$,,$& +&)M$& )(T$&&#,T 5 2'*&C$ )(/)($ unsigned short calc timer2unsigned short step rate 6 1unsigned short timer if2step rate ; -%< ST$, '&$S#$(C=3 step rate 0 1-%< ST$, '&$S#$(C= if2step rate ; ?::::3 5 // )f steprate ; ?:!CJ ;; step 4 times 1step rate 0 2step rate ;; ?3[:4Afff 1step loops 0 4 5 else if2step rate ; 1::::3 5 // )f steprate ; 1:!CJ ;; step ? times 1step rate 0 2step rate ;; 13[:4Gfff 1step loops 0 ? 5 6 else 1step loops 0 1 5 12if2step rate < 2' C,#/E:::::33 step rate 0 2' C,#/E:::::

step rate 80 2' C,#/E:::::31 // Correct for minimal speed if2step rate ;0 2BU?EF33 // higher step rate higher step rate // 6 unsigned short ta"le address 0 2unsigned 1Nshort3[speed loo!upta"le fastN2unsigned char32step rate;;B3ON: 12unsigned char tmp step rate 0 2step rate [ :4::ff 12unsigned short gain 0 2unsigned short3pgm read word near2ta"le addressW? 12-ulti#1F<BtoC1F2timerI tmp step rateI gain 1timer 0 2unsigned short3pgm read word near2ta"le address3 8 timer 5 else lower step rates // 6 1Nunsigned short ta"le address 0 2unsigned short3[speed loo!upta"le slowN:ON: 1ta"le address W0 22step rate3;;13 [ :4fffc 12timer 0 2unsigned short3pgm read word near2ta"le address timer 80 222unsigned short3pgm read word near2ta"le addressW?3 U 2unsigned 12char32step rate [ :4:::G33;;A 5 2if2timer < 1::3 5 timer 0 1::1 6//2?:!CJ this should never happen 1return timer 5 )nitialiJes the trapeJoid generator from the current "loc!. Called whenever a new // ."loc! "egins // 23'*&C$ )(/)($ void trapeJoid generator reset 6 ifdef %+M%(C$# 1advance 0 current "loc!8;initial advance 1final advance 0 current "loc!8;final advance +o $ steps W advance steps // 12e steps W0 22advance ;;B3 8 old advance 1old advance 0 advance ;;B endif# 1deceleration time 0 : step rate to timer interval // 1acc step rate 0 current "loc!8;initial rate 12acceleration time 0 calc timer2acc step rate 1*C&1% 0 acceleration time 12*C&1% nominal 0 calc timer2current "loc!8;nominal rate 5 .The Stepper +river )nterrupt" 8 This timer interrupt is the wor!horse" // )t pops "loc!s from the "loc! "uffer and e4ecutes them "H pulsing the stepper pins // .appropriatelH 2)S&2T)-$&1 C*-,% vect 6

)f there is no current "loc!I attempt to pop one from the "uffer // 6 2if 2current "loc! 00 (#// T%nHthing in the "uffer // 123current "loc! 0 plan get current "loc! 6 2if 2current "loc! Y0 (#// 123trapeJoid generator reset 12counter 4 0 82current "loc!8;step event count ;; 1 1counter H 0 counter 4 1counter J 0 counter 4 1counter e 0 counter 4 1step events completed 0 : ifdef %+M%(C$# // 1e steps 0 : // endif# // 5 6 else .*C&1%0?:::1 // 1!CJ 5 5 6 2if 2current "loc! Y0 (#// Set directions T* +* This should "e done once during init of trapeJoid. // $ndstops 8; interrupt 1out "its 0 current "loc!8;direction "its Set direction and chec! limit switches // if 22out "its [ 21<<< %<)S33 Y0 :3 5 // 8direction 12@&)T$2< +)& ,)(I )(M$&T < +)& CC$CQ $(+ST*,S 6 if < -)( ,)( ; 81# 12"ool 4 min endstop02&$%+2< -)( ,)(3 Y0 < $(+ST*, )(M$&T 6 22if24 min endstop [[ old 4 min endstop [[ 2current "loc!8;steps 4 ; : 2if2Yis homing 1endstop 4 hit0true else 1step events completed 0 current "loc!8;step event count 5 else 6 1endstop 4 hit0false 5 1old 4 min endstop 0 4 min endstop else# 1endstop 4 hit0false endif# 5 5 else 5 // Wdirection 12@&)T$2< +)& ,)(IY)(M$&T < +)&

CC$CQ $(+ST*,S 6 if < -%< ,)( ; 81# 12"ool 4 ma4 endstop02&$%+2< -%< ,)(3 Y0 < $(+ST*, )(M$&T 622if24 ma4 endstop [[ old 4 ma4 endstop [[ 2current "loc!8;steps 4 ; : 2if2Yis homing 1endstop 4 hit0true else 1step events completed 0 current "loc!8;step event count 5 else 6 1endstop 4 hit0false 5 1old 4 ma4 endstop 0 4 ma4 endstop else# 1endstop 4 hit0false endif# 5 5 if 22out "its [ 21<<= %<)S33 Y0 :3 5 // 8direction 12@&)T$2= +)& ,)(I)(M$&T = +)& CC$CQ $(+ST*,S 6 if = -)( ,)( ; 81# 12"ool H min endstop02&$%+2= -)( ,)(3 Y0 = $(+ST*, )(M$&T 6 22if2H min endstop [[ old H min endstop [[ 2current "loc!8;steps H ; : 2if2Yis homing 1endstop H hit0true else 1step events completed 0 current "loc!8;step event count 5 else 6 1endstop H hit0false 5 1old H min endstop 0 H min endstop else# 1endstop H hit0false endif# 5 5 else 5 // Wdirection 12@&)T$2= +)& ,)(IY)(M$&T = +)& CC$CQ $(+ST*,S 6 if = -%< ,)( ; 81# 12"ool H ma4 endstop02&$%+2= -%< ,)(3 Y0 = $(+ST*, )(M$&T 622if2H ma4 endstop [[ old H ma4 endstop [[ 2current "loc!8;steps H ; :

2if2Yis homing 1endstop H hit0true else 1step events completed 0 current "loc!8;step event count 5 else 6 1endstop H hit0false 5 1old H ma4 endstop 0 H ma4 endstop else# 1endstop H hit0false endif# 5 5 if 22out "its [ 21<<> %<)S33 Y0 :3 5 // 8direction 12@&)T$2> +)& ,)(I)(M$&T > +)& CC$CQ $(+ST*,S 6 if > -)( ,)( ; 81# 12"ool J min endstop02&$%+2> -)( ,)(3 Y0 > $(+ST*, )(M$&T 6 22if2J min endstop [[ old J min endstop [[ 2current "loc!8;steps J ; : 2if2Yis homing 1endstop J hit0true else 1step events completed 0 current "loc!8;step event count 5 else 6 1endstop J hit0false 5 1old J min endstop 0 J min endstop else# 1endstop J hit0false endif# 5 5 else 5 // Wdirection 12@&)T$2> +)& ,)(IY)(M$&T > +)& CC$CQ $(+ST*,S 6 if > -%< ,)( ; 81# 12"ool J ma4 endstop02&$%+2> -%< ,)(3 Y0 > $(+ST*, )(M$&T 6 22if2J ma4 endstop [[ old J ma4 endstop [[ 2current "loc!8;steps J ; : 2if2Yis homing 1endstop J hit0true else 1step events completed 0 current "loc!8;step event count 5

else 6 1endstop J hit0false 5 1old J ma4 endstop 0 J ma4 endstop else# 1endstop J hit0false endif# 5 5 ifndef %+M%(C$# if 22out "its [ 21<<$ %<)S33 Y0 :3 5 // 8direction 12@&)T$2$ +)& ,)(I)(M$&T $ +)& 5 else 5 // Wdirection 12@&)T$2$ +)& ,)(IY)(M$&T $ +)& 5 endif //Y%+M%(C$#

for2intB t i0:1 i < step loops1 iWW3 5 // Ta!e multiple steps per interrupt 2'or high 2speed moves ifdef %+M%(C$# 1counter e W0 current "loc!8;steps e 6 2if 2counter e ; : 1counter e 80 current "loc!8;step event count if 22out "its [ 21<<$ %<)S33 Y0 :3 5 // 8 direction 188e steps 5 6 else 1WWe steps 5 5 endif //%+M%(C$# 1counter 4 W0 current "loc!8;steps 4 6 2if 2counter 4 ; : 2if2Yendstop 4 hit 6 2if2virtual steps 4 188virtual steps 4 else 12@&)T$2< ST$, ,)(I C).C 5 else 1WWvirtual steps 4

1counter 4 80 current "loc!8;step event count 12@&)T$2< ST$, ,)(I /*@ 5 1counter H W0 current "loc!8;steps H 6 2if 2counter H ; : 2if2Yendstop H hit 6 2if2virtual steps H 188virtual steps H else 12@&)T$2= ST$, ,)(I C).C 5 else 1WWvirtual steps H 1counter H 80 current "loc!8;step event count 12@&)T$2= ST$, ,)(I /*@ 5 1counter J W0 current "loc!8;steps J 6 2if 2counter J ; : 2if2Yendstop J hit 6 2if2virtual steps J 188virtual steps J else 12@&)T$2> ST$, ,)(I C).C 5 else 1WWvirtual steps J 1counter J 80 current "loc!8;step event count 12@&)T$2> ST$, ,)(I /*@ 5 ifndef %+M%(C$# 1counter e W0 current "loc!8;steps e 6 2if 2counter e ; : 12@&)T$2$ ST$, ,)(I C).C 1counter e 80 current "loc!8;step event count 12@&)T$2$ ST$, ,)(I /*@ 5 endif //Y%+M%(C$# 1step events completed W0 1 1if2step events completed ;0 current "loc!8;step event count3 "rea! 5

Calculare new timer value // 1unsigned short timer 1unsigned short step rate 6 2if 2step events completed <0 2unsigned long int3current "loc!8;accelerate until -ulti#?4<?4toC1F2acc step rateI acceleration timeI current "loc!8 12;acceleration rate 1acc step rate W0 current "loc!8;initial rate upper limit // 2if2acc step rate ; current "loc!8;nominal rate 1acc step rate 0 current "loc!8;nominal rate step rate to timer interval // 12timer 0 calc timer2acc step rate 1*C&1% 0 timer 1acceleration time W0 timer ifdef %+M%(C$# 6 2WWfor2intB t i0:1 i < step loops1 i 1advance W0 advance rate 5 1if2advance ; current "loc!8;advance3 advance 0 current "loc!8;advance// +o $ steps W advance steps // 12e steps W0 22advance ;;B3 8 old advance 1old advance 0 advance ;;B endif# 5 else if 2step events completed ; 2unsigned long int3current "loc!8 6 2;decelerate after -ulti#?4<?4toC1F2step rateI deceleration timeI current "loc!8 12;acceleration rate if2step rate ; acc step rate3 5 // Chec! step rate staHs positive 1step rate 0 current "loc!8;final rate 5 6 else .step rate 0 acc step rate 8 step rate1 // +ecelerate from aceleration end point 5 lower limit // 2if2step rate < current "loc!8;final rate 1step rate 0 current "loc!8;final rate step rate to timer interval // 12timer 0 calc timer2step rate 1*C&1% 0 timer 1deceleration time W0 timer ifdef %+M%(C$# 6 2WWfor2intB t i0:1 i < step loops1 i

1advance 80 advance rate 5 1if2advance < final advance3 advance 0 final advance +o $ steps W advance steps // 12e steps W0 22advance ;;B3 8 old advance 1old advance 0 advance ;;B endif //%+M%(C$# 5 6 else 1*C&1% 0 *C&1% nominal 5 )f current "loc! is finishedI reset pointer // 6 2if 2step events completed ;0 current "loc!8;step event count 1current "loc! 0 (#// 123plan discard current "loc! 5 5 5 ifdef %+M%(C$# 1unsigned char old *C&:% 1Timer interrupt for $. e steps is set in the main routine // Timer : is shared with millies // 2)S&2T)-$&: C*-,% vect 6 2old *C&:% W0 E?1 // _1:!CJ interrupt 2?E:::: / ?F 0 DF1E!CJ 1*C&:% 0 old *C&:% 2Set $ direction 2+epends on $ direction W advance // 2WWfor2unsigned char i0:1 i<41i 6 2if 2e steps Y0 : 6 12@&)T$2$: ST$, ,)(I /*@ 6 2if 2e steps < : 12@&)T$2$: +)& ,)(I )(M$&T $: +)& 1WWe steps 12@&)T$2$: ST$, ,)(I C).C 5 6 2else if 2e steps ; : 12@&)T$2$: +)& ,)(I Y)(M$&T $: +)& 188e steps 12@&)T$2$: ST$, ,)(I C).C 5 5 5 5 endif // %+M%(C$#

23void st init 6 waveform generation 0 :1:: 0 CTC // 12TCC&1V [0 _21<<@.-1A 12TCC&1V \0 21<<@.-1? 12TCC&1% [0 _21<<@.-11 12TCC&1% [0 _21<<@.-1: 2output mode 0 :: 2disconnected // 12TCC&1% [0 _2A<<C*-1%: 12TCC&1% [0 _2A<<C*-1V: Set the timer pre8scaler // .enerallH we use a divider of BI resulting in a ?-CJ timer // freRuencH on a 1F-CJ -C#. )f Hou are going to change thisI "e // sure to regenerate speed loo!upta"le.h with // create speed loo!upta"le.pH // TCC&1V 0 2TCC&1V [ _2:4:G<<CS1:33 \ 2?<<CS1:31 // ?-CJ timer 1*C&1% 0 :44::: 1TC(T1 0 : 123$(%V/$ ST$,,$& +&)M$& )(T$&&#,T ifdef %+M%(C$# 2if defined2TCC&:%3 [[ defined2@.-:1# 12TCC&:% [0 _21<<@.-:1 12TCC&:% [0 _21<<@.-:: endif# 1e steps 0 : 12T)-SQ: \0 21<<*C)$:% endif //%+M%(C$# ifdef $(+ST*,S *(/= '*& C*-)(.# 12ena"le endstops2false else# 12ena"le endstops2true endif# 123sei 5 Vloc! until all "uffered steps are e4ecuted // 23void st sHnchroniJe 6 6 223while2"loc!s Rueued 123manage heater 12manage inactivitH21 2if 2-)()-#- '%( ST%&T S,$$+ ; :# 123manage fan start speed endif#

5 5 ifdef +$V#.# 6 2void log message2charU message 12Serial.print2"+$V#."31 Serial.println2message 5 6 2void log "ool2charU messageI "ool value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log int2charU messageI int value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log long2charU messageI long value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log float2charU messageI float value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log uint2charU messageI unsigned int value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log ulong2charU messageI unsigned long value Serial.print2"+$V#."31 Serial.print2message31 Serial.print2"7 "31 12Serial.println2value 5 6 2void log int arraH2charU messageI int valueNOI int arraH lenght 12"6 7"3Serial.print2"+$V#."31 Serial.print2message31 Serial.print 62WWfor2int i0:1 i < arraH lenght1 i 12NSerial.print2valueNi 12" I"3if2i Y0 arraH lenght813 Serial.print 5 12"5"3Serial.println 5 6 2void log long arraH2charU messageI long valueNOI int arraH lenght 12"6 7"3Serial.print2"+$V#."31 Serial.print2message31 Serial.print

62WWfor2int i0:1 i < arraH lenght1 i 12NSerial.print2valueNi 12" I"3if2i Y0 arraH lenght813 Serial.print 5 12"5"3Serial.println 5 6 2void log float arraH2charU messageI float valueNOI int arraH lenght 12"6 7"3Serial.print2"+$V#."31 Serial.print2message31 Serial.print 62WWfor2int i0:1 i < arraH lenght1 i 12NSerial.print2valueNi 12" I"3if2i Y0 arraH lenght813 Serial.print 5 12"5"3Serial.println 5 6 2void log uint arraH2charU messageI unsigned int valueNOI int arraH lenght 12"6 7"3Serial.print2"+$V#."31 Serial.print2message31 Serial.print 62WWfor2int i0:1 i < arraH lenght1 i 12NSerial.print2valueNi 12" I"3if2i Y0 arraH lenght813 Serial.print 5 12"5"3Serial.println 5 6 2void log ulong arraH2charU messageI unsigned long valueNOI int arraH lenght 12"6 7"3Serial.print2"+$V#."31 Serial.print2message31 Serial.print 62WWfor2int i0:1 i < arraH lenght1 i 12NSerial.print2valueNi 12" I"3if2i Y0 arraH lenght813 Serial.print 5 12"5"3Serial.println 5 endif#

You might also like