My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Marlin_main.cpp 304KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * About Marlin
  24. *
  25. * This firmware is a mashup between Sprinter and grbl.
  26. * - https://github.com/kliment/Sprinter
  27. * - https://github.com/simen/grbl/tree
  28. *
  29. * It has preliminary support for Matthew Roberts advance algorithm
  30. * - http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
  31. */
  32. #include "Marlin.h"
  33. #if HAS_ABL
  34. #include "vector_3.h"
  35. #endif
  36. #if ENABLED(AUTO_BED_LEVELING_LINEAR)
  37. #include "qr_solve.h"
  38. #elif ENABLED(MESH_BED_LEVELING)
  39. #include "mesh_bed_leveling.h"
  40. #endif
  41. #if ENABLED(BEZIER_CURVE_SUPPORT)
  42. #include "planner_bezier.h"
  43. #endif
  44. #include "ultralcd.h"
  45. #include "planner.h"
  46. #include "stepper.h"
  47. #include "endstops.h"
  48. #include "temperature.h"
  49. #include "cardreader.h"
  50. #include "configuration_store.h"
  51. #include "language.h"
  52. #include "pins_arduino.h"
  53. #include "math.h"
  54. #include "nozzle.h"
  55. #include "duration_t.h"
  56. #include "types.h"
  57. #if ENABLED(USE_WATCHDOG)
  58. #include "watchdog.h"
  59. #endif
  60. #if ENABLED(BLINKM)
  61. #include "blinkm.h"
  62. #include "Wire.h"
  63. #endif
  64. #if HAS_SERVOS
  65. #include "servo.h"
  66. #endif
  67. #if HAS_DIGIPOTSS
  68. #include <SPI.h>
  69. #endif
  70. #if ENABLED(DAC_STEPPER_CURRENT)
  71. #include "stepper_dac.h"
  72. #endif
  73. #if ENABLED(EXPERIMENTAL_I2CBUS)
  74. #include "twibus.h"
  75. #endif
  76. /**
  77. * Look here for descriptions of G-codes:
  78. * - http://linuxcnc.org/handbook/gcode/g-code.html
  79. * - http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
  80. *
  81. * Help us document these G-codes online:
  82. * - https://github.com/MarlinFirmware/Marlin/wiki/G-Code-in-Marlin
  83. * - http://reprap.org/wiki/G-code
  84. *
  85. * -----------------
  86. * Implemented Codes
  87. * -----------------
  88. *
  89. * "G" Codes
  90. *
  91. * G0 -> G1
  92. * G1 - Coordinated Movement X Y Z E
  93. * G2 - CW ARC
  94. * G3 - CCW ARC
  95. * G4 - Dwell S<seconds> or P<milliseconds>
  96. * G5 - Cubic B-spline with XYZE destination and IJPQ offsets
  97. * G10 - Retract filament according to settings of M207
  98. * G11 - Retract recover filament according to settings of M208
  99. * G12 - Clean tool
  100. * G20 - Set input units to inches
  101. * G21 - Set input units to millimeters
  102. * G28 - Home one or more axes
  103. * G29 - Detailed Z probe, probes the bed at 3 or more points. Will fail if you haven't homed yet.
  104. * G30 - Single Z probe, probes bed at current XY location.
  105. * G31 - Dock sled (Z_PROBE_SLED only)
  106. * G32 - Undock sled (Z_PROBE_SLED only)
  107. * G38 - Probe target - similar to G28 except it uses the Z_Probe for all three axis
  108. * G90 - Use Absolute Coordinates
  109. * G91 - Use Relative Coordinates
  110. * G92 - Set current position to coordinates given
  111. *
  112. * "M" Codes
  113. *
  114. * M0 - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
  115. * M1 - Same as M0
  116. * M17 - Enable/Power all stepper motors
  117. * M18 - Disable all stepper motors; same as M84
  118. * M20 - List SD card. (Requires SDSUPPORT)
  119. * M21 - Init SD card. (Requires SDSUPPORT)
  120. * M22 - Release SD card. (Requires SDSUPPORT)
  121. * M23 - Select SD file: "M23 /path/file.gco". (Requires SDSUPPORT)
  122. * M24 - Start/resume SD print. (Requires SDSUPPORT)
  123. * M25 - Pause SD print. (Requires SDSUPPORT)
  124. * M26 - Set SD position in bytes: "M26 S12345". (Requires SDSUPPORT)
  125. * M27 - Report SD print status. (Requires SDSUPPORT)
  126. * M28 - Start SD write: "M28 /path/file.gco". (Requires SDSUPPORT)
  127. * M29 - Stop SD write. (Requires SDSUPPORT)
  128. * M30 - Delete file from SD: "M30 /path/file.gco"
  129. * M31 - Report time since last M109 or SD card start to serial.
  130. * M32 - Select file and start SD print: "M32 [S<bytepos>] !/path/file.gco#". (Requires SDSUPPORT)
  131. * Use P to run other files as sub-programs: "M32 P !filename#"
  132. * The '#' is necessary when calling from within sd files, as it stops buffer prereading
  133. * M33 - Get the longname version of a path. (Requires LONG_FILENAME_HOST_SUPPORT)
  134. * M42 - Change pin status via gcode: M42 P<pin> S<value>. LED pin assumed if P is omitted.
  135. * M48 - Measure Z Probe repeatability: M48 P<points> X<pos> Y<pos> V<level> E<engage> L<legs>. (Requires Z_MIN_PROBE_REPEATABILITY_TEST)
  136. * M75 - Start the print job timer.
  137. * M76 - Pause the print job timer.
  138. * M77 - Stop the print job timer.
  139. * M78 - Show statistical information about the print jobs. (Requires PRINTCOUNTER)
  140. * M80 - Turn on Power Supply. (Requires POWER_SUPPLY)
  141. * M81 - Turn off Power Supply. (Requires POWER_SUPPLY)
  142. * M82 - Set E codes absolute (default).
  143. * M83 - Set E codes relative while in Absolute (G90) mode.
  144. * M84 - Disable steppers until next move, or use S<seconds> to specify an idle
  145. * duration after which steppers should turn off. S0 disables the timeout.
  146. * M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
  147. * M92 - Set planner.axis_steps_per_mm for one or more axes.
  148. * M104 - Set extruder target temp.
  149. * M105 - Report current temperatures.
  150. * M106 - Fan on.
  151. * M107 - Fan off.
  152. * M108 - Break out of heating loops (M109, M190, M303). With no controller, breaks out of M0/M1. (Requires EMERGENCY_PARSER)
  153. * M109 - Sxxx Wait for extruder current temp to reach target temp. Waits only when heating
  154. * Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
  155. * IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
  156. * M110 - Set the current line number. (Used by host printing)
  157. * M111 - Set debug flags: "M111 S<flagbits>". See flag bits defined in enum.h.
  158. * M112 - Emergency stop.
  159. * M113 - Get or set the timeout interval for Host Keepalive "busy" messages. (Requires HOST_KEEPALIVE_FEATURE)
  160. * M114 - Report current position.
  161. * M115 - Report capabilities.
  162. * M117 - Display a message on the controller screen. (Requires an LCD)
  163. * M119 - Report endstops status.
  164. * M120 - Enable endstops detection.
  165. * M121 - Disable endstops detection.
  166. * M126 - Solenoid Air Valve Open. (Requires BARICUDA)
  167. * M127 - Solenoid Air Valve Closed. (Requires BARICUDA)
  168. * M128 - EtoP Open. (Requires BARICUDA)
  169. * M129 - EtoP Closed. (Requires BARICUDA)
  170. * M140 - Set bed target temp. S<temp>
  171. * M145 - Set heatup values for materials on the LCD. H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
  172. * M149 - Set temperature units. (Requires TEMPERATURE_UNITS_SUPPORT)
  173. * M150 - Set BlinkM Color R<red> U<green> B<blue>. Values 0-255. (Requires BLINKM)
  174. * M163 - Set a single proportion for a mixing extruder. (Requires MIXING_EXTRUDER)
  175. * M164 - Save the mix as a virtual extruder. (Requires MIXING_EXTRUDER and MIXING_VIRTUAL_TOOLS)
  176. * M165 - Set the proportions for a mixing extruder. Use parameters ABCDHI to set the mixing factors. (Requires MIXING_EXTRUDER)
  177. * M190 - Sxxx Wait for bed current temp to reach target temp. ** Waits only when heating! **
  178. * Rxxx Wait for bed current temp to reach target temp. ** Waits for heating or cooling. **
  179. * M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
  180. * M201 - Set max acceleration in units/s^2 for print moves: "M201 X<accel> Y<accel> Z<accel> E<accel>"
  181. * M202 - Set max acceleration in units/s^2 for travel moves: "M202 X<accel> Y<accel> Z<accel> E<accel>" ** UNUSED IN MARLIN! **
  182. * M203 - Set maximum feedrate: "M203 X<fr> Y<fr> Z<fr> E<fr>" in units/sec.
  183. * M204 - Set default acceleration in units/sec^2: P<printing> R<extruder_only> T<travel>
  184. * M205 - Set advanced settings. Current units apply:
  185. S<print> T<travel> minimum speeds
  186. B<minimum segment time>
  187. X<max xy jerk>, Z<max Z jerk>, E<max E jerk>
  188. * M206 - Set additional homing offset.
  189. * M207 - Set Retract Length: S<length>, Feedrate: F<units/min>, and Z lift: Z<distance>. (Requires FWRETRACT)
  190. * M208 - Set Recover (unretract) Additional (!) Length: S<length> and Feedrate: F<units/min>. (Requires FWRETRACT)
  191. * M209 - Turn Automatic Retract Detection on/off: S<0|1> (For slicers that don't support G10/11). (Requires FWRETRACT)
  192. Every normal extrude-only move will be classified as retract depending on the direction.
  193. * M211 - Enable, Disable, and/or Report software endstops: S<0|1>
  194. * M218 - Set a tool offset: "M218 T<index> X<offset> Y<offset>". (Requires 2 or more extruders)
  195. * M220 - Set Feedrate Percentage: "M220 S<percent>" (i.e., "FR" on the LCD)
  196. * M221 - Set Flow Percentage: "M221 S<percent>"
  197. * M226 - Wait until a pin is in a given state: "M226 P<pin> S<state>"
  198. * M240 - Trigger a camera to take a photograph. (Requires CHDK or PHOTOGRAPH_PIN)
  199. * M250 - Set LCD contrast: "M250 C<contrast>" (0-63). (Requires LCD support)
  200. * M280 - Set servo position absolute: "M280 P<index> S<angle|µs>". (Requires servos)
  201. * M300 - Play beep sound S<frequency Hz> P<duration ms>
  202. * M301 - Set PID parameters P I and D. (Requires PIDTEMP)
  203. * M302 - Allow cold extrudes, or set the minimum extrude S<temperature>. (Requires PREVENT_COLD_EXTRUSION)
  204. * M303 - PID relay autotune S<temperature> sets the target temperature. Default 150C. (Requires PIDTEMP)
  205. * M304 - Set bed PID parameters P I and D. (Requires PIDTEMPBED)
  206. * M380 - Activate solenoid on active extruder. (Requires EXT_SOLENOID)
  207. * M381 - Disable all solenoids. (Requires EXT_SOLENOID)
  208. * M400 - Finish all moves.
  209. * M401 - Lower Z probe. (Requires a probe)
  210. * M402 - Raise Z probe. (Requires a probe)
  211. * M404 - Display or set the Nominal Filament Width: "W<diameter>". (Requires FILAMENT_WIDTH_SENSOR)
  212. * M405 - Enable Filament Sensor flow control. "M405 D<delay_cm>". (Requires FILAMENT_WIDTH_SENSOR)
  213. * M406 - Disable Filament Sensor flow control. (Requires FILAMENT_WIDTH_SENSOR)
  214. * M407 - Display measured filament diameter in millimeters. (Requires FILAMENT_WIDTH_SENSOR)
  215. * M410 - Quickstop. Abort all planned moves.
  216. * M420 - Enable/Disable Leveling (with current values) S1=enable S0=disable (Requires MESH_BED_LEVELING or ABL)
  217. * M421 - Set a single Z coordinate in the Mesh Leveling grid. X<units> Y<units> Z<units> (Requires MESH_BED_LEVELING)
  218. * M428 - Set the home_offset based on the current_position. Nearest edge applies.
  219. * M500 - Store parameters in EEPROM. (Requires EEPROM_SETTINGS)
  220. * M501 - Restore parameters from EEPROM. (Requires EEPROM_SETTINGS)
  221. * M502 - Revert to the default "factory settings". ** Does not write them to EEPROM! **
  222. * M503 - Print the current settings (in memory): "M503 S<verbose>". S0 specifies compact output.
  223. * M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
  224. * M600 - Pause for filament change: "M600 X<pos> Y<pos> Z<raise> E<first_retract> L<later_retract>". (Requires FILAMENT_CHANGE_FEATURE)
  225. * M665 - Set delta configurations: "M665 L<diagonal rod> R<delta radius> S<segments/s>" (Requires DELTA)
  226. * M666 - Set delta endstop adjustment. (Requires DELTA)
  227. * M605 - Set dual x-carriage movement mode: "M605 S<mode> [X<x_offset>] [R<temp_offset>]". (Requires DUAL_X_CARRIAGE)
  228. * M851 - Set Z probe's Z offset in current units. (Negative = below the nozzle.)
  229. * M907 - Set digital trimpot motor current using axis codes. (Requires a board with digital trimpots)
  230. * M908 - Control digital trimpot directly. (Requires DAC_STEPPER_CURRENT or DIGIPOTSS_PIN)
  231. * M909 - Print digipot/DAC current value. (Requires DAC_STEPPER_CURRENT)
  232. * M910 - Commit digipot/DAC value to external EEPROM via I2C. (Requires DAC_STEPPER_CURRENT)
  233. * M350 - Set microstepping mode. (Requires digital microstepping pins.)
  234. * M351 - Toggle MS1 MS2 pins directly. (Requires digital microstepping pins.)
  235. *
  236. * ************ SCARA Specific - This can change to suit future G-code regulations
  237. * M360 - SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
  238. * M361 - SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
  239. * M362 - SCARA calibration: Move to cal-position PsiA (0 deg calibration)
  240. * M363 - SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
  241. * M364 - SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
  242. * ************* SCARA End ***************
  243. *
  244. * ************ Custom codes - This can change to suit future G-code regulations
  245. * M100 - Watch Free Memory (For Debugging). (Requires M100_FREE_MEMORY_WATCHER)
  246. * M928 - Start SD logging: "M928 filename.gco". Stop with M29. (Requires SDSUPPORT)
  247. * M999 - Restart after being stopped by error
  248. *
  249. * "T" Codes
  250. *
  251. * T0-T3 - Select an extruder (tool) by index: "T<n> F<units/min>"
  252. *
  253. */
  254. #if ENABLED(M100_FREE_MEMORY_WATCHER)
  255. void gcode_M100();
  256. #endif
  257. #if ENABLED(SDSUPPORT)
  258. CardReader card;
  259. #endif
  260. #if ENABLED(EXPERIMENTAL_I2CBUS)
  261. TWIBus i2c;
  262. #endif
  263. #ifdef G38_2_3
  264. bool G38_flag = false; // init G38 flags
  265. bool G38_flag_pass = false;
  266. #endif
  267. bool Running = true;
  268. uint8_t marlin_debug_flags = DEBUG_NONE;
  269. float current_position[NUM_AXIS] = { 0.0 };
  270. static float destination[NUM_AXIS] = { 0.0 };
  271. bool axis_known_position[XYZ] = { false };
  272. bool axis_homed[XYZ] = { false };
  273. static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
  274. static char command_queue[BUFSIZE][MAX_CMD_SIZE];
  275. static char* current_command, *current_command_args;
  276. static uint8_t cmd_queue_index_r = 0,
  277. cmd_queue_index_w = 0,
  278. commands_in_queue = 0;
  279. #if ENABLED(INCH_MODE_SUPPORT)
  280. float linear_unit_factor = 1.0;
  281. float volumetric_unit_factor = 1.0;
  282. #endif
  283. #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
  284. TempUnit input_temp_units = TEMPUNIT_C;
  285. #endif
  286. /**
  287. * Feed rates are often configured with mm/m
  288. * but the planner and stepper like mm/s units.
  289. */
  290. float constexpr homing_feedrate_mm_s[] = {
  291. #if ENABLED(DELTA)
  292. MMM_TO_MMS(HOMING_FEEDRATE_Z), MMM_TO_MMS(HOMING_FEEDRATE_Z),
  293. #else
  294. MMM_TO_MMS(HOMING_FEEDRATE_XY), MMM_TO_MMS(HOMING_FEEDRATE_XY),
  295. #endif
  296. MMM_TO_MMS(HOMING_FEEDRATE_Z), 0
  297. };
  298. static float feedrate_mm_s = MMM_TO_MMS(1500.0), saved_feedrate_mm_s;
  299. int feedrate_percentage = 100, saved_feedrate_percentage;
  300. bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
  301. int flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
  302. bool volumetric_enabled = false;
  303. float filament_size[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_NOMINAL_FILAMENT_DIA);
  304. float volumetric_multiplier[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0);
  305. // The distance that XYZ has been offset by G92. Reset by G28.
  306. float position_shift[XYZ] = { 0 };
  307. // This offset is added to the configured home position.
  308. // Set by M206, M428, or menu item. Saved to EEPROM.
  309. float home_offset[XYZ] = { 0 };
  310. // Software Endstops are based on the configured limits.
  311. #if ENABLED(min_software_endstops) || ENABLED(max_software_endstops)
  312. bool soft_endstops_enabled = true;
  313. #endif
  314. float soft_endstop_min[XYZ] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS },
  315. soft_endstop_max[XYZ] = { X_MAX_POS, Y_MAX_POS, Z_MAX_POS };
  316. #if FAN_COUNT > 0
  317. int fanSpeeds[FAN_COUNT] = { 0 };
  318. #endif
  319. // The active extruder (tool). Set with T<extruder> command.
  320. uint8_t active_extruder = 0;
  321. // Relative Mode. Enable with G91, disable with G90.
  322. static bool relative_mode = false;
  323. volatile bool wait_for_heatup = true;
  324. #if ENABLED(EMERGENCY_PARSER) && DISABLED(ULTIPANEL)
  325. volatile bool wait_for_user = false;
  326. #endif
  327. const char errormagic[] PROGMEM = "Error:";
  328. const char echomagic[] PROGMEM = "echo:";
  329. const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
  330. static int serial_count = 0;
  331. // GCode parameter pointer used by code_seen(), code_value_float(), etc.
  332. static char* seen_pointer;
  333. // Next Immediate GCode Command pointer. NULL if none.
  334. const char* queued_commands_P = NULL;
  335. const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
  336. // Inactivity shutdown
  337. millis_t previous_cmd_ms = 0;
  338. static millis_t max_inactive_time = 0;
  339. static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL;
  340. // Print Job Timer
  341. #if ENABLED(PRINTCOUNTER)
  342. PrintCounter print_job_timer = PrintCounter();
  343. #else
  344. Stopwatch print_job_timer = Stopwatch();
  345. #endif
  346. // Buzzer - I2C on the LCD or a BEEPER_PIN
  347. #if ENABLED(LCD_USE_I2C_BUZZER)
  348. #define BUZZ(d,f) lcd_buzz(d, f)
  349. #elif HAS_BUZZER
  350. Buzzer buzzer;
  351. #define BUZZ(d,f) buzzer.tone(d, f)
  352. #else
  353. #define BUZZ(d,f) NOOP
  354. #endif
  355. static uint8_t target_extruder;
  356. #if HAS_BED_PROBE
  357. float zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER;
  358. #endif
  359. #define PLANNER_XY_FEEDRATE() (min(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]))
  360. #if HAS_ABL
  361. float xy_probe_feedrate_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
  362. #define XY_PROBE_FEEDRATE_MM_S xy_probe_feedrate_mm_s
  363. #elif defined(XY_PROBE_SPEED)
  364. #define XY_PROBE_FEEDRATE_MM_S MMM_TO_MMS(XY_PROBE_SPEED)
  365. #else
  366. #define XY_PROBE_FEEDRATE_MM_S PLANNER_XY_FEEDRATE()
  367. #endif
  368. #if ENABLED(Z_DUAL_ENDSTOPS)
  369. float z_endstop_adj = 0;
  370. #endif
  371. // Extruder offsets
  372. #if HOTENDS > 1
  373. float hotend_offset[][HOTENDS] = {
  374. HOTEND_OFFSET_X,
  375. HOTEND_OFFSET_Y
  376. #ifdef HOTEND_OFFSET_Z
  377. , HOTEND_OFFSET_Z
  378. #endif
  379. };
  380. #endif
  381. #if HAS_Z_SERVO_ENDSTOP
  382. const int z_servo_angle[2] = Z_SERVO_ANGLES;
  383. #endif
  384. #if ENABLED(BARICUDA)
  385. int baricuda_valve_pressure = 0;
  386. int baricuda_e_to_p_pressure = 0;
  387. #endif
  388. #if ENABLED(FWRETRACT)
  389. bool autoretract_enabled = false;
  390. bool retracted[EXTRUDERS] = { false };
  391. bool retracted_swap[EXTRUDERS] = { false };
  392. float retract_length = RETRACT_LENGTH;
  393. float retract_length_swap = RETRACT_LENGTH_SWAP;
  394. float retract_feedrate_mm_s = RETRACT_FEEDRATE;
  395. float retract_zlift = RETRACT_ZLIFT;
  396. float retract_recover_length = RETRACT_RECOVER_LENGTH;
  397. float retract_recover_length_swap = RETRACT_RECOVER_LENGTH_SWAP;
  398. float retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
  399. #endif // FWRETRACT
  400. #if ENABLED(ULTIPANEL) && HAS_POWER_SWITCH
  401. bool powersupply =
  402. #if ENABLED(PS_DEFAULT_OFF)
  403. false
  404. #else
  405. true
  406. #endif
  407. ;
  408. #endif
  409. #if ENABLED(DELTA)
  410. #define SIN_60 0.8660254037844386
  411. #define COS_60 0.5
  412. float delta[ABC],
  413. endstop_adj[ABC] = { 0 };
  414. // these are the default values, can be overriden with M665
  415. float delta_radius = DELTA_RADIUS,
  416. delta_tower1_x = -SIN_60 * (delta_radius + DELTA_RADIUS_TRIM_TOWER_1), // front left tower
  417. delta_tower1_y = -COS_60 * (delta_radius + DELTA_RADIUS_TRIM_TOWER_1),
  418. delta_tower2_x = SIN_60 * (delta_radius + DELTA_RADIUS_TRIM_TOWER_2), // front right tower
  419. delta_tower2_y = -COS_60 * (delta_radius + DELTA_RADIUS_TRIM_TOWER_2),
  420. delta_tower3_x = 0, // back middle tower
  421. delta_tower3_y = (delta_radius + DELTA_RADIUS_TRIM_TOWER_3),
  422. delta_diagonal_rod = DELTA_DIAGONAL_ROD,
  423. delta_diagonal_rod_trim_tower_1 = DELTA_DIAGONAL_ROD_TRIM_TOWER_1,
  424. delta_diagonal_rod_trim_tower_2 = DELTA_DIAGONAL_ROD_TRIM_TOWER_2,
  425. delta_diagonal_rod_trim_tower_3 = DELTA_DIAGONAL_ROD_TRIM_TOWER_3,
  426. delta_diagonal_rod_2_tower_1 = sq(delta_diagonal_rod + delta_diagonal_rod_trim_tower_1),
  427. delta_diagonal_rod_2_tower_2 = sq(delta_diagonal_rod + delta_diagonal_rod_trim_tower_2),
  428. delta_diagonal_rod_2_tower_3 = sq(delta_diagonal_rod + delta_diagonal_rod_trim_tower_3),
  429. delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND,
  430. delta_clip_start_height = Z_MAX_POS;
  431. float delta_safe_distance_from_top();
  432. #else
  433. static bool home_all_axis = true;
  434. #endif
  435. #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
  436. int bilinear_grid_spacing[2] = { 0 }, bilinear_start[2] = { 0 };
  437. float bed_level_grid[ABL_GRID_POINTS_X][ABL_GRID_POINTS_Y];
  438. #endif
  439. #if IS_SCARA
  440. // Float constants for SCARA calculations
  441. const float L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2,
  442. L1_2 = sq(float(L1)), L1_2_2 = 2.0 * L1_2,
  443. L2_2 = sq(float(L2));
  444. float delta_segments_per_second = SCARA_SEGMENTS_PER_SECOND,
  445. delta[ABC];
  446. #endif
  447. float cartes[XYZ] = { 0 };
  448. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  449. bool filament_sensor = false; //M405 turns on filament_sensor control, M406 turns it off
  450. float filament_width_nominal = DEFAULT_NOMINAL_FILAMENT_DIA, // Nominal filament width. Change with M404
  451. filament_width_meas = DEFAULT_MEASURED_FILAMENT_DIA; // Measured filament diameter
  452. int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1]; // Ring buffer to delayed measurement. Store extruder factor after subtracting 100
  453. int filwidth_delay_index[2] = { 0, -1 }; // Indexes into ring buffer
  454. int meas_delay_cm = MEASUREMENT_DELAY_CM; //distance delay setting
  455. #endif
  456. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  457. static bool filament_ran_out = false;
  458. #endif
  459. #if ENABLED(FILAMENT_CHANGE_FEATURE)
  460. FilamentChangeMenuResponse filament_change_menu_response;
  461. #endif
  462. #if ENABLED(MIXING_EXTRUDER)
  463. float mixing_factor[MIXING_STEPPERS];
  464. #if MIXING_VIRTUAL_TOOLS > 1
  465. float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
  466. #endif
  467. #endif
  468. static bool send_ok[BUFSIZE];
  469. #if HAS_SERVOS
  470. Servo servo[NUM_SERVOS];
  471. #define MOVE_SERVO(I, P) servo[I].move(P)
  472. #if HAS_Z_SERVO_ENDSTOP
  473. #define DEPLOY_Z_SERVO() MOVE_SERVO(Z_ENDSTOP_SERVO_NR, z_servo_angle[0])
  474. #define STOW_Z_SERVO() MOVE_SERVO(Z_ENDSTOP_SERVO_NR, z_servo_angle[1])
  475. #endif
  476. #endif
  477. #ifdef CHDK
  478. millis_t chdkHigh = 0;
  479. boolean chdkActive = false;
  480. #endif
  481. #if ENABLED(PID_EXTRUSION_SCALING)
  482. int lpq_len = 20;
  483. #endif
  484. #if ENABLED(HOST_KEEPALIVE_FEATURE)
  485. static MarlinBusyState busy_state = NOT_BUSY;
  486. static millis_t next_busy_signal_ms = 0;
  487. uint8_t host_keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
  488. #define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0)
  489. #else
  490. #define host_keepalive() ;
  491. #define KEEPALIVE_STATE(n) ;
  492. #endif // HOST_KEEPALIVE_FEATURE
  493. #define DEFINE_PGM_READ_ANY(type, reader) \
  494. static inline type pgm_read_any(const type *p) \
  495. { return pgm_read_##reader##_near(p); }
  496. DEFINE_PGM_READ_ANY(float, float);
  497. DEFINE_PGM_READ_ANY(signed char, byte);
  498. #define XYZ_CONSTS_FROM_CONFIG(type, array, CONFIG) \
  499. static const PROGMEM type array##_P[XYZ] = \
  500. { X_##CONFIG, Y_##CONFIG, Z_##CONFIG }; \
  501. static inline type array(int axis) \
  502. { return pgm_read_any(&array##_P[axis]); }
  503. XYZ_CONSTS_FROM_CONFIG(float, base_min_pos, MIN_POS);
  504. XYZ_CONSTS_FROM_CONFIG(float, base_max_pos, MAX_POS);
  505. XYZ_CONSTS_FROM_CONFIG(float, base_home_pos, HOME_POS);
  506. XYZ_CONSTS_FROM_CONFIG(float, max_length, MAX_LENGTH);
  507. XYZ_CONSTS_FROM_CONFIG(float, home_bump_mm, HOME_BUMP_MM);
  508. XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR);
  509. /**
  510. * ***************************************************************************
  511. * ******************************** FUNCTIONS ********************************
  512. * ***************************************************************************
  513. */
  514. void stop();
  515. void get_available_commands();
  516. void process_next_command();
  517. void prepare_move_to_destination();
  518. void get_cartesian_from_steppers();
  519. void set_current_from_steppers_for_axis(const AxisEnum axis);
  520. #if ENABLED(ARC_SUPPORT)
  521. void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise);
  522. #endif
  523. #if ENABLED(BEZIER_CURVE_SUPPORT)
  524. void plan_cubic_move(const float offset[4]);
  525. #endif
  526. void serial_echopair_P(const char* s_P, const char *v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  527. void serial_echopair_P(const char* s_P, char v) { serialprintPGM(s_P); SERIAL_CHAR(v); }
  528. void serial_echopair_P(const char* s_P, int v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  529. void serial_echopair_P(const char* s_P, long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  530. void serial_echopair_P(const char* s_P, float v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  531. void serial_echopair_P(const char* s_P, double v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  532. void serial_echopair_P(const char* s_P, unsigned long v) { serialprintPGM(s_P); SERIAL_ECHO(v); }
  533. void tool_change(const uint8_t tmp_extruder, const float fr_mm_s=0.0, bool no_move=false);
  534. static void report_current_position();
  535. #if ENABLED(DEBUG_LEVELING_FEATURE)
  536. void print_xyz(const char* prefix, const char* suffix, const float x, const float y, const float z) {
  537. serialprintPGM(prefix);
  538. SERIAL_ECHOPAIR("(", x);
  539. SERIAL_ECHOPAIR(", ", y);
  540. SERIAL_ECHOPAIR(", ", z);
  541. SERIAL_ECHOPGM(")");
  542. if (suffix) serialprintPGM(suffix);
  543. else SERIAL_EOL;
  544. }
  545. void print_xyz(const char* prefix, const char* suffix, const float xyz[]) {
  546. print_xyz(prefix, suffix, xyz[X_AXIS], xyz[Y_AXIS], xyz[Z_AXIS]);
  547. }
  548. #if HAS_ABL
  549. void print_xyz(const char* prefix, const char* suffix, const vector_3 &xyz) {
  550. print_xyz(prefix, suffix, xyz.x, xyz.y, xyz.z);
  551. }
  552. #endif
  553. #define DEBUG_POS(SUFFIX,VAR) do { \
  554. print_xyz(PSTR(STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); } while(0)
  555. #endif
  556. /**
  557. * sync_plan_position
  558. *
  559. * Set the planner/stepper positions directly from current_position with
  560. * no kinematic translation. Used for homing axes and cartesian/core syncing.
  561. */
  562. inline void sync_plan_position() {
  563. #if ENABLED(DEBUG_LEVELING_FEATURE)
  564. if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position);
  565. #endif
  566. planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
  567. }
  568. inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); }
  569. #if IS_KINEMATIC
  570. inline void sync_plan_position_kinematic() {
  571. #if ENABLED(DEBUG_LEVELING_FEATURE)
  572. if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position);
  573. #endif
  574. inverse_kinematics(current_position);
  575. planner.set_position_mm(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS]);
  576. }
  577. #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
  578. #else
  579. #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position()
  580. #endif
  581. #if ENABLED(SDSUPPORT)
  582. #include "SdFatUtil.h"
  583. int freeMemory() { return SdFatUtil::FreeRam(); }
  584. #else
  585. extern "C" {
  586. extern unsigned int __bss_end;
  587. extern unsigned int __heap_start;
  588. extern void* __brkval;
  589. int freeMemory() {
  590. int free_memory;
  591. if ((int)__brkval == 0)
  592. free_memory = ((int)&free_memory) - ((int)&__bss_end);
  593. else
  594. free_memory = ((int)&free_memory) - ((int)__brkval);
  595. return free_memory;
  596. }
  597. }
  598. #endif //!SDSUPPORT
  599. #if ENABLED(DIGIPOT_I2C)
  600. extern void digipot_i2c_set_current(int channel, float current);
  601. extern void digipot_i2c_init();
  602. #endif
  603. /**
  604. * Inject the next "immediate" command, when possible.
  605. * Return true if any immediate commands remain to inject.
  606. */
  607. static bool drain_queued_commands_P() {
  608. if (queued_commands_P != NULL) {
  609. size_t i = 0;
  610. char c, cmd[30];
  611. strncpy_P(cmd, queued_commands_P, sizeof(cmd) - 1);
  612. cmd[sizeof(cmd) - 1] = '\0';
  613. while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
  614. cmd[i] = '\0';
  615. if (enqueue_and_echo_command(cmd)) { // success?
  616. if (c) // newline char?
  617. queued_commands_P += i + 1; // advance to the next command
  618. else
  619. queued_commands_P = NULL; // nul char? no more commands
  620. }
  621. }
  622. return (queued_commands_P != NULL); // return whether any more remain
  623. }
  624. /**
  625. * Record one or many commands to run from program memory.
  626. * Aborts the current queue, if any.
  627. * Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards
  628. */
  629. void enqueue_and_echo_commands_P(const char* pgcode) {
  630. queued_commands_P = pgcode;
  631. drain_queued_commands_P(); // first command executed asap (when possible)
  632. }
  633. void clear_command_queue() {
  634. cmd_queue_index_r = cmd_queue_index_w;
  635. commands_in_queue = 0;
  636. }
  637. /**
  638. * Once a new command is in the ring buffer, call this to commit it
  639. */
  640. inline void _commit_command(bool say_ok) {
  641. send_ok[cmd_queue_index_w] = say_ok;
  642. cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
  643. commands_in_queue++;
  644. }
  645. /**
  646. * Copy a command directly into the main command buffer, from RAM.
  647. * Returns true if successfully adds the command
  648. */
  649. inline bool _enqueuecommand(const char* cmd, bool say_ok=false) {
  650. if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
  651. strcpy(command_queue[cmd_queue_index_w], cmd);
  652. _commit_command(say_ok);
  653. return true;
  654. }
  655. void enqueue_and_echo_command_now(const char* cmd) {
  656. while (!enqueue_and_echo_command(cmd)) idle();
  657. }
  658. /**
  659. * Enqueue with Serial Echo
  660. */
  661. bool enqueue_and_echo_command(const char* cmd, bool say_ok/*=false*/) {
  662. if (_enqueuecommand(cmd, say_ok)) {
  663. SERIAL_ECHO_START;
  664. SERIAL_ECHOPAIR(MSG_Enqueueing, cmd);
  665. SERIAL_ECHOLNPGM("\"");
  666. return true;
  667. }
  668. return false;
  669. }
  670. void setup_killpin() {
  671. #if HAS_KILL
  672. SET_INPUT(KILL_PIN);
  673. WRITE(KILL_PIN, HIGH);
  674. #endif
  675. }
  676. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  677. void setup_filrunoutpin() {
  678. SET_INPUT(FIL_RUNOUT_PIN);
  679. #if ENABLED(ENDSTOPPULLUP_FIL_RUNOUT)
  680. WRITE(FIL_RUNOUT_PIN, HIGH);
  681. #endif
  682. }
  683. #endif
  684. // Set home pin
  685. void setup_homepin(void) {
  686. #if HAS_HOME
  687. SET_INPUT(HOME_PIN);
  688. WRITE(HOME_PIN, HIGH);
  689. #endif
  690. }
  691. void setup_photpin() {
  692. #if HAS_PHOTOGRAPH
  693. OUT_WRITE(PHOTOGRAPH_PIN, LOW);
  694. #endif
  695. }
  696. void setup_powerhold() {
  697. #if HAS_SUICIDE
  698. OUT_WRITE(SUICIDE_PIN, HIGH);
  699. #endif
  700. #if HAS_POWER_SWITCH
  701. #if ENABLED(PS_DEFAULT_OFF)
  702. OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP);
  703. #else
  704. OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE);
  705. #endif
  706. #endif
  707. }
  708. void suicide() {
  709. #if HAS_SUICIDE
  710. OUT_WRITE(SUICIDE_PIN, LOW);
  711. #endif
  712. }
  713. void servo_init() {
  714. #if NUM_SERVOS >= 1 && HAS_SERVO_0
  715. servo[0].attach(SERVO0_PIN);
  716. servo[0].detach(); // Just set up the pin. We don't have a position yet. Don't move to a random position.
  717. #endif
  718. #if NUM_SERVOS >= 2 && HAS_SERVO_1
  719. servo[1].attach(SERVO1_PIN);
  720. servo[1].detach();
  721. #endif
  722. #if NUM_SERVOS >= 3 && HAS_SERVO_2
  723. servo[2].attach(SERVO2_PIN);
  724. servo[2].detach();
  725. #endif
  726. #if NUM_SERVOS >= 4 && HAS_SERVO_3
  727. servo[3].attach(SERVO3_PIN);
  728. servo[3].detach();
  729. #endif
  730. #if HAS_Z_SERVO_ENDSTOP
  731. /**
  732. * Set position of Z Servo Endstop
  733. *
  734. * The servo might be deployed and positioned too low to stow
  735. * when starting up the machine or rebooting the board.
  736. * There's no way to know where the nozzle is positioned until
  737. * homing has been done - no homing with z-probe without init!
  738. *
  739. */
  740. STOW_Z_SERVO();
  741. #endif
  742. }
  743. /**
  744. * Stepper Reset (RigidBoard, et.al.)
  745. */
  746. #if HAS_STEPPER_RESET
  747. void disableStepperDrivers() {
  748. OUT_WRITE(STEPPER_RESET_PIN, LOW); // drive it down to hold in reset motor driver chips
  749. }
  750. void enableStepperDrivers() { SET_INPUT(STEPPER_RESET_PIN); } // set to input, which allows it to be pulled high by pullups
  751. #endif
  752. #if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
  753. void i2c_on_receive(int bytes) { // just echo all bytes received to serial
  754. i2c.receive(bytes);
  755. }
  756. void i2c_on_request() { // just send dummy data for now
  757. i2c.reply("Hello World!\n");
  758. }
  759. #endif
  760. void gcode_line_error(const char* err, bool doFlush = true) {
  761. SERIAL_ERROR_START;
  762. serialprintPGM(err);
  763. SERIAL_ERRORLN(gcode_LastN);
  764. //Serial.println(gcode_N);
  765. if (doFlush) FlushSerialRequestResend();
  766. serial_count = 0;
  767. }
  768. inline void get_serial_commands() {
  769. static char serial_line_buffer[MAX_CMD_SIZE];
  770. static boolean serial_comment_mode = false;
  771. // If the command buffer is empty for too long,
  772. // send "wait" to indicate Marlin is still waiting.
  773. #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
  774. static millis_t last_command_time = 0;
  775. millis_t ms = millis();
  776. if (commands_in_queue == 0 && !MYSERIAL.available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
  777. SERIAL_ECHOLNPGM(MSG_WAIT);
  778. last_command_time = ms;
  779. }
  780. #endif
  781. /**
  782. * Loop while serial characters are incoming and the queue is not full
  783. */
  784. while (commands_in_queue < BUFSIZE && MYSERIAL.available() > 0) {
  785. char serial_char = MYSERIAL.read();
  786. /**
  787. * If the character ends the line
  788. */
  789. if (serial_char == '\n' || serial_char == '\r') {
  790. serial_comment_mode = false; // end of line == end of comment
  791. if (!serial_count) continue; // skip empty lines
  792. serial_line_buffer[serial_count] = 0; // terminate string
  793. serial_count = 0; //reset buffer
  794. char* command = serial_line_buffer;
  795. while (*command == ' ') command++; // skip any leading spaces
  796. char* npos = (*command == 'N') ? command : NULL; // Require the N parameter to start the line
  797. char* apos = strchr(command, '*');
  798. if (npos) {
  799. boolean M110 = strstr_P(command, PSTR("M110")) != NULL;
  800. if (M110) {
  801. char* n2pos = strchr(command + 4, 'N');
  802. if (n2pos) npos = n2pos;
  803. }
  804. gcode_N = strtol(npos + 1, NULL, 10);
  805. if (gcode_N != gcode_LastN + 1 && !M110) {
  806. gcode_line_error(PSTR(MSG_ERR_LINE_NO));
  807. return;
  808. }
  809. if (apos) {
  810. byte checksum = 0, count = 0;
  811. while (command[count] != '*') checksum ^= command[count++];
  812. if (strtol(apos + 1, NULL, 10) != checksum) {
  813. gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH));
  814. return;
  815. }
  816. // if no errors, continue parsing
  817. }
  818. else {
  819. gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM));
  820. return;
  821. }
  822. gcode_LastN = gcode_N;
  823. // if no errors, continue parsing
  824. }
  825. else if (apos) { // No '*' without 'N'
  826. gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
  827. return;
  828. }
  829. // Movement commands alert when stopped
  830. if (IsStopped()) {
  831. char* gpos = strchr(command, 'G');
  832. if (gpos) {
  833. int codenum = strtol(gpos + 1, NULL, 10);
  834. switch (codenum) {
  835. case 0:
  836. case 1:
  837. case 2:
  838. case 3:
  839. SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
  840. LCD_MESSAGEPGM(MSG_STOPPED);
  841. break;
  842. }
  843. }
  844. }
  845. #if DISABLED(EMERGENCY_PARSER)
  846. // If command was e-stop process now
  847. if (strcmp(command, "M108") == 0) wait_for_heatup = false;
  848. if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
  849. if (strcmp(command, "M410") == 0) { quickstop_stepper(); }
  850. #endif
  851. #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
  852. last_command_time = ms;
  853. #endif
  854. // Add the command to the queue
  855. _enqueuecommand(serial_line_buffer, true);
  856. }
  857. else if (serial_count >= MAX_CMD_SIZE - 1) {
  858. // Keep fetching, but ignore normal characters beyond the max length
  859. // The command will be injected when EOL is reached
  860. }
  861. else if (serial_char == '\\') { // Handle escapes
  862. if (MYSERIAL.available() > 0) {
  863. // if we have one more character, copy it over
  864. serial_char = MYSERIAL.read();
  865. if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
  866. }
  867. // otherwise do nothing
  868. }
  869. else { // it's not a newline, carriage return or escape char
  870. if (serial_char == ';') serial_comment_mode = true;
  871. if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
  872. }
  873. } // queue has space, serial has data
  874. }
  875. #if ENABLED(SDSUPPORT)
  876. inline void get_sdcard_commands() {
  877. static bool stop_buffering = false,
  878. sd_comment_mode = false;
  879. if (!card.sdprinting) return;
  880. /**
  881. * '#' stops reading from SD to the buffer prematurely, so procedural
  882. * macro calls are possible. If it occurs, stop_buffering is triggered
  883. * and the buffer is run dry; this character _can_ occur in serial com
  884. * due to checksums, however, no checksums are used in SD printing.
  885. */
  886. if (commands_in_queue == 0) stop_buffering = false;
  887. uint16_t sd_count = 0;
  888. bool card_eof = card.eof();
  889. while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) {
  890. int16_t n = card.get();
  891. char sd_char = (char)n;
  892. card_eof = card.eof();
  893. if (card_eof || n == -1
  894. || sd_char == '\n' || sd_char == '\r'
  895. || ((sd_char == '#' || sd_char == ':') && !sd_comment_mode)
  896. ) {
  897. if (card_eof) {
  898. SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
  899. card.printingHasFinished();
  900. card.checkautostart(true);
  901. }
  902. else if (n == -1) {
  903. SERIAL_ERROR_START;
  904. SERIAL_ECHOLNPGM(MSG_SD_ERR_READ);
  905. }
  906. if (sd_char == '#') stop_buffering = true;
  907. sd_comment_mode = false; //for new command
  908. if (!sd_count) continue; //skip empty lines
  909. command_queue[cmd_queue_index_w][sd_count] = '\0'; //terminate string
  910. sd_count = 0; //clear buffer
  911. _commit_command(false);
  912. }
  913. else if (sd_count >= MAX_CMD_SIZE - 1) {
  914. /**
  915. * Keep fetching, but ignore normal characters beyond the max length
  916. * The command will be injected when EOL is reached
  917. */
  918. }
  919. else {
  920. if (sd_char == ';') sd_comment_mode = true;
  921. if (!sd_comment_mode) command_queue[cmd_queue_index_w][sd_count++] = sd_char;
  922. }
  923. }
  924. }
  925. #endif // SDSUPPORT
  926. /**
  927. * Add to the circular command queue the next command from:
  928. * - The command-injection queue (queued_commands_P)
  929. * - The active serial input (usually USB)
  930. * - The SD card file being actively printed
  931. */
  932. void get_available_commands() {
  933. // if any immediate commands remain, don't get other commands yet
  934. if (drain_queued_commands_P()) return;
  935. get_serial_commands();
  936. #if ENABLED(SDSUPPORT)
  937. get_sdcard_commands();
  938. #endif
  939. }
  940. inline bool code_has_value() {
  941. int i = 1;
  942. char c = seen_pointer[i];
  943. while (c == ' ') c = seen_pointer[++i];
  944. if (c == '-' || c == '+') c = seen_pointer[++i];
  945. if (c == '.') c = seen_pointer[++i];
  946. return NUMERIC(c);
  947. }
  948. inline float code_value_float() {
  949. float ret;
  950. char* e = strchr(seen_pointer, 'E');
  951. if (e) {
  952. *e = 0;
  953. ret = strtod(seen_pointer + 1, NULL);
  954. *e = 'E';
  955. }
  956. else
  957. ret = strtod(seen_pointer + 1, NULL);
  958. return ret;
  959. }
  960. inline unsigned long code_value_ulong() { return strtoul(seen_pointer + 1, NULL, 10); }
  961. inline long code_value_long() { return strtol(seen_pointer + 1, NULL, 10); }
  962. inline int code_value_int() { return (int)strtol(seen_pointer + 1, NULL, 10); }
  963. inline uint16_t code_value_ushort() { return (uint16_t)strtoul(seen_pointer + 1, NULL, 10); }
  964. inline uint8_t code_value_byte() { return (uint8_t)(constrain(strtol(seen_pointer + 1, NULL, 10), 0, 255)); }
  965. inline bool code_value_bool() { return !code_has_value() || code_value_byte() > 0; }
  966. #if ENABLED(INCH_MODE_SUPPORT)
  967. inline void set_input_linear_units(LinearUnit units) {
  968. switch (units) {
  969. case LINEARUNIT_INCH:
  970. linear_unit_factor = 25.4;
  971. break;
  972. case LINEARUNIT_MM:
  973. default:
  974. linear_unit_factor = 1.0;
  975. break;
  976. }
  977. volumetric_unit_factor = pow(linear_unit_factor, 3.0);
  978. }
  979. inline float axis_unit_factor(int axis) {
  980. return (axis == E_AXIS && volumetric_enabled ? volumetric_unit_factor : linear_unit_factor);
  981. }
  982. inline float code_value_linear_units() { return code_value_float() * linear_unit_factor; }
  983. inline float code_value_axis_units(int axis) { return code_value_float() * axis_unit_factor(axis); }
  984. inline float code_value_per_axis_unit(int axis) { return code_value_float() / axis_unit_factor(axis); }
  985. #else
  986. inline float code_value_linear_units() { return code_value_float(); }
  987. inline float code_value_axis_units(int axis) { UNUSED(axis); return code_value_float(); }
  988. inline float code_value_per_axis_unit(int axis) { UNUSED(axis); return code_value_float(); }
  989. #endif
  990. #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
  991. inline void set_input_temp_units(TempUnit units) { input_temp_units = units; }
  992. float code_value_temp_abs() {
  993. switch (input_temp_units) {
  994. case TEMPUNIT_C:
  995. return code_value_float();
  996. case TEMPUNIT_F:
  997. return (code_value_float() - 32) * 0.5555555556;
  998. case TEMPUNIT_K:
  999. return code_value_float() - 272.15;
  1000. default:
  1001. return code_value_float();
  1002. }
  1003. }
  1004. float code_value_temp_diff() {
  1005. switch (input_temp_units) {
  1006. case TEMPUNIT_C:
  1007. case TEMPUNIT_K:
  1008. return code_value_float();
  1009. case TEMPUNIT_F:
  1010. return code_value_float() * 0.5555555556;
  1011. default:
  1012. return code_value_float();
  1013. }
  1014. }
  1015. #else
  1016. float code_value_temp_abs() { return code_value_float(); }
  1017. float code_value_temp_diff() { return code_value_float(); }
  1018. #endif
  1019. FORCE_INLINE millis_t code_value_millis() { return code_value_ulong(); }
  1020. inline millis_t code_value_millis_from_seconds() { return code_value_float() * 1000; }
  1021. bool code_seen(char code) {
  1022. seen_pointer = strchr(current_command_args, code);
  1023. return (seen_pointer != NULL); // Return TRUE if the code-letter was found
  1024. }
  1025. /**
  1026. * Set target_extruder from the T parameter or the active_extruder
  1027. *
  1028. * Returns TRUE if the target is invalid
  1029. */
  1030. bool get_target_extruder_from_command(int code) {
  1031. if (code_seen('T')) {
  1032. if (code_value_byte() >= EXTRUDERS) {
  1033. SERIAL_ECHO_START;
  1034. SERIAL_CHAR('M');
  1035. SERIAL_ECHO(code);
  1036. SERIAL_ECHOLNPAIR(" " MSG_INVALID_EXTRUDER " ", code_value_byte());
  1037. return true;
  1038. }
  1039. target_extruder = code_value_byte();
  1040. }
  1041. else
  1042. target_extruder = active_extruder;
  1043. return false;
  1044. }
  1045. #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
  1046. bool extruder_duplication_enabled = false; // Used in Dual X mode 2
  1047. #endif
  1048. #if ENABLED(DUAL_X_CARRIAGE)
  1049. #define DXC_FULL_CONTROL_MODE 0
  1050. #define DXC_AUTO_PARK_MODE 1
  1051. #define DXC_DUPLICATION_MODE 2
  1052. static int dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
  1053. static float x_home_pos(int extruder) {
  1054. if (extruder == 0)
  1055. return LOGICAL_X_POSITION(base_home_pos(X_AXIS));
  1056. else
  1057. /**
  1058. * In dual carriage mode the extruder offset provides an override of the
  1059. * second X-carriage offset when homed - otherwise X2_HOME_POS is used.
  1060. * This allow soft recalibration of the second extruder offset position
  1061. * without firmware reflash (through the M218 command).
  1062. */
  1063. return (hotend_offset[X_AXIS][1] > 0) ? hotend_offset[X_AXIS][1] : X2_HOME_POS;
  1064. }
  1065. static int x_home_dir(int extruder) {
  1066. return (extruder == 0) ? X_HOME_DIR : X2_HOME_DIR;
  1067. }
  1068. static float inactive_extruder_x_pos = X2_MAX_POS; // used in mode 0 & 1
  1069. static bool active_extruder_parked = false; // used in mode 1 & 2
  1070. static float raised_parked_position[NUM_AXIS]; // used in mode 1
  1071. static millis_t delayed_move_time = 0; // used in mode 1
  1072. static float duplicate_extruder_x_offset = DEFAULT_DUPLICATION_X_OFFSET; // used in mode 2
  1073. static float duplicate_extruder_temp_offset = 0; // used in mode 2
  1074. #endif //DUAL_X_CARRIAGE
  1075. /**
  1076. * Software endstops can be used to monitor the open end of
  1077. * an axis that has a hardware endstop on the other end. Or
  1078. * they can prevent axes from moving past endstops and grinding.
  1079. *
  1080. * To keep doing their job as the coordinate system changes,
  1081. * the software endstop positions must be refreshed to remain
  1082. * at the same positions relative to the machine.
  1083. */
  1084. void update_software_endstops(AxisEnum axis) {
  1085. float offs = LOGICAL_POSITION(0, axis);
  1086. #if ENABLED(DUAL_X_CARRIAGE)
  1087. if (axis == X_AXIS) {
  1088. float dual_max_x = max(hotend_offset[X_AXIS][1], X2_MAX_POS);
  1089. if (active_extruder != 0) {
  1090. soft_endstop_min[X_AXIS] = X2_MIN_POS + offs;
  1091. soft_endstop_max[X_AXIS] = dual_max_x + offs;
  1092. return;
  1093. }
  1094. else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) {
  1095. soft_endstop_min[X_AXIS] = base_min_pos(X_AXIS) + offs;
  1096. soft_endstop_max[X_AXIS] = min(base_max_pos(X_AXIS), dual_max_x - duplicate_extruder_x_offset) + offs;
  1097. return;
  1098. }
  1099. }
  1100. else
  1101. #endif
  1102. {
  1103. soft_endstop_min[axis] = base_min_pos(axis) + offs;
  1104. soft_endstop_max[axis] = base_max_pos(axis) + offs;
  1105. }
  1106. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1107. if (DEBUGGING(LEVELING)) {
  1108. SERIAL_ECHOPAIR("For ", axis_codes[axis]);
  1109. SERIAL_ECHOPAIR(" axis:\n home_offset = ", home_offset[axis]);
  1110. SERIAL_ECHOPAIR("\n position_shift = ", position_shift[axis]);
  1111. SERIAL_ECHOPAIR("\n soft_endstop_min = ", soft_endstop_min[axis]);
  1112. SERIAL_ECHOLNPAIR("\n soft_endstop_max = ", soft_endstop_max[axis]);
  1113. }
  1114. #endif
  1115. #if ENABLED(DELTA)
  1116. if (axis == Z_AXIS)
  1117. delta_clip_start_height = soft_endstop_max[axis] - delta_safe_distance_from_top();
  1118. #endif
  1119. }
  1120. /**
  1121. * Change the home offset for an axis, update the current
  1122. * position and the software endstops to retain the same
  1123. * relative distance to the new home.
  1124. *
  1125. * Since this changes the current_position, code should
  1126. * call sync_plan_position soon after this.
  1127. */
  1128. static void set_home_offset(AxisEnum axis, float v) {
  1129. current_position[axis] += v - home_offset[axis];
  1130. home_offset[axis] = v;
  1131. update_software_endstops(axis);
  1132. }
  1133. /**
  1134. * Set an axis' current position to its home position (after homing).
  1135. *
  1136. * For Core and Cartesian robots this applies one-to-one when an
  1137. * individual axis has been homed.
  1138. *
  1139. * DELTA should wait until all homing is done before setting the XYZ
  1140. * current_position to home, because homing is a single operation.
  1141. * In the case where the axis positions are already known and previously
  1142. * homed, DELTA could home to X or Y individually by moving either one
  1143. * to the center. However, homing Z always homes XY and Z.
  1144. *
  1145. * SCARA should wait until all XY homing is done before setting the XY
  1146. * current_position to home, because neither X nor Y is at home until
  1147. * both are at home. Z can however be homed individually.
  1148. *
  1149. */
  1150. static void set_axis_is_at_home(AxisEnum axis) {
  1151. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1152. if (DEBUGGING(LEVELING)) {
  1153. SERIAL_ECHOPAIR(">>> set_axis_is_at_home(", axis_codes[axis]);
  1154. SERIAL_ECHOLNPGM(")");
  1155. }
  1156. #endif
  1157. axis_known_position[axis] = axis_homed[axis] = true;
  1158. position_shift[axis] = 0;
  1159. update_software_endstops(axis);
  1160. #if ENABLED(DUAL_X_CARRIAGE)
  1161. if (axis == X_AXIS && (active_extruder != 0 || dual_x_carriage_mode == DXC_DUPLICATION_MODE)) {
  1162. if (active_extruder != 0)
  1163. current_position[X_AXIS] = x_home_pos(active_extruder);
  1164. else
  1165. current_position[X_AXIS] = LOGICAL_X_POSITION(base_home_pos(X_AXIS));
  1166. update_software_endstops(X_AXIS);
  1167. return;
  1168. }
  1169. #endif
  1170. #if ENABLED(MORGAN_SCARA)
  1171. /**
  1172. * Morgan SCARA homes XY at the same time
  1173. */
  1174. if (axis == X_AXIS || axis == Y_AXIS) {
  1175. float homeposition[XYZ];
  1176. LOOP_XYZ(i) homeposition[i] = LOGICAL_POSITION(base_home_pos(i), i);
  1177. // SERIAL_ECHOPAIR("homeposition X:", homeposition[X_AXIS]);
  1178. // SERIAL_ECHOLNPAIR(" Y:", homeposition[Y_AXIS]);
  1179. /**
  1180. * Get Home position SCARA arm angles using inverse kinematics,
  1181. * and calculate homing offset using forward kinematics
  1182. */
  1183. inverse_kinematics(homeposition);
  1184. forward_kinematics_SCARA(delta[A_AXIS], delta[B_AXIS]);
  1185. // SERIAL_ECHOPAIR("Cartesian X:", cartes[X_AXIS]);
  1186. // SERIAL_ECHOLNPAIR(" Y:", cartes[Y_AXIS]);
  1187. current_position[axis] = LOGICAL_POSITION(cartes[axis], axis);
  1188. /**
  1189. * SCARA home positions are based on configuration since the actual
  1190. * limits are determined by the inverse kinematic transform.
  1191. */
  1192. soft_endstop_min[axis] = base_min_pos(axis); // + (cartes[axis] - base_home_pos(axis));
  1193. soft_endstop_max[axis] = base_max_pos(axis); // + (cartes[axis] - base_home_pos(axis));
  1194. }
  1195. else
  1196. #endif
  1197. {
  1198. current_position[axis] = LOGICAL_POSITION(base_home_pos(axis), axis);
  1199. }
  1200. /**
  1201. * Z Probe Z Homing? Account for the probe's Z offset.
  1202. */
  1203. #if HAS_BED_PROBE && Z_HOME_DIR < 0
  1204. if (axis == Z_AXIS) {
  1205. #if HOMING_Z_WITH_PROBE
  1206. current_position[Z_AXIS] -= zprobe_zoffset;
  1207. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1208. if (DEBUGGING(LEVELING)) {
  1209. SERIAL_ECHOLNPGM("*** Z HOMED WITH PROBE (Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) ***");
  1210. SERIAL_ECHOLNPAIR("> zprobe_zoffset = ", zprobe_zoffset);
  1211. }
  1212. #endif
  1213. #elif ENABLED(DEBUG_LEVELING_FEATURE)
  1214. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("*** Z HOMED TO ENDSTOP (Z_MIN_PROBE_ENDSTOP) ***");
  1215. #endif
  1216. }
  1217. #endif
  1218. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1219. if (DEBUGGING(LEVELING)) {
  1220. SERIAL_ECHOPAIR("> home_offset[", axis_codes[axis]);
  1221. SERIAL_ECHOLNPAIR("] = ", home_offset[axis]);
  1222. DEBUG_POS("", current_position);
  1223. SERIAL_ECHOPAIR("<<< set_axis_is_at_home(", axis_codes[axis]);
  1224. SERIAL_ECHOLNPGM(")");
  1225. }
  1226. #endif
  1227. }
  1228. /**
  1229. * Some planner shorthand inline functions
  1230. */
  1231. inline float get_homing_bump_feedrate(AxisEnum axis) {
  1232. int constexpr homing_bump_divisor[] = HOMING_BUMP_DIVISOR;
  1233. int hbd = homing_bump_divisor[axis];
  1234. if (hbd < 1) {
  1235. hbd = 10;
  1236. SERIAL_ECHO_START;
  1237. SERIAL_ECHOLNPGM("Warning: Homing Bump Divisor < 1");
  1238. }
  1239. return homing_feedrate_mm_s[axis] / hbd;
  1240. }
  1241. //
  1242. // line_to_current_position
  1243. // Move the planner to the current position from wherever it last moved
  1244. // (or from wherever it has been told it is located).
  1245. //
  1246. inline void line_to_current_position() {
  1247. planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate_mm_s, active_extruder);
  1248. }
  1249. //
  1250. // line_to_destination
  1251. // Move the planner, not necessarily synced with current_position
  1252. //
  1253. inline void line_to_destination(float fr_mm_s) {
  1254. planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], fr_mm_s, active_extruder);
  1255. }
  1256. inline void line_to_destination() { line_to_destination(feedrate_mm_s); }
  1257. inline void set_current_to_destination() { memcpy(current_position, destination, sizeof(current_position)); }
  1258. inline void set_destination_to_current() { memcpy(destination, current_position, sizeof(destination)); }
  1259. #if IS_KINEMATIC
  1260. /**
  1261. * Calculate delta, start a line, and set current_position to destination
  1262. */
  1263. void prepare_uninterpolated_move_to_destination(const float fr_mm_s=0.0) {
  1264. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1265. if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_uninterpolated_move_to_destination", destination);
  1266. #endif
  1267. if ( current_position[X_AXIS] == destination[X_AXIS]
  1268. && current_position[Y_AXIS] == destination[Y_AXIS]
  1269. && current_position[Z_AXIS] == destination[Z_AXIS]
  1270. && current_position[E_AXIS] == destination[E_AXIS]
  1271. ) return;
  1272. refresh_cmd_timeout();
  1273. inverse_kinematics(destination);
  1274. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], MMS_SCALED(fr_mm_s ? fr_mm_s : feedrate_mm_s), active_extruder);
  1275. set_current_to_destination();
  1276. }
  1277. #endif // IS_KINEMATIC
  1278. /**
  1279. * Plan a move to (X, Y, Z) and set the current_position
  1280. * The final current_position may not be the one that was requested
  1281. */
  1282. void do_blocking_move_to(const float &x, const float &y, const float &z, const float &fr_mm_s /*=0.0*/) {
  1283. float old_feedrate_mm_s = feedrate_mm_s;
  1284. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1285. if (DEBUGGING(LEVELING)) print_xyz(PSTR(">>> do_blocking_move_to"), NULL, x, y, z);
  1286. #endif
  1287. #if ENABLED(DELTA)
  1288. feedrate_mm_s = fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S;
  1289. set_destination_to_current(); // sync destination at the start
  1290. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1291. if (DEBUGGING(LEVELING)) DEBUG_POS("set_destination_to_current", destination);
  1292. #endif
  1293. // when in the danger zone
  1294. if (current_position[Z_AXIS] > delta_clip_start_height) {
  1295. if (z > delta_clip_start_height) { // staying in the danger zone
  1296. destination[X_AXIS] = x; // move directly (uninterpolated)
  1297. destination[Y_AXIS] = y;
  1298. destination[Z_AXIS] = z;
  1299. prepare_uninterpolated_move_to_destination(); // set_current_to_destination
  1300. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1301. if (DEBUGGING(LEVELING)) DEBUG_POS("danger zone move", current_position);
  1302. #endif
  1303. return;
  1304. }
  1305. else {
  1306. destination[Z_AXIS] = delta_clip_start_height;
  1307. prepare_uninterpolated_move_to_destination(); // set_current_to_destination
  1308. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1309. if (DEBUGGING(LEVELING)) DEBUG_POS("zone border move", current_position);
  1310. #endif
  1311. }
  1312. }
  1313. if (z > current_position[Z_AXIS]) { // raising?
  1314. destination[Z_AXIS] = z;
  1315. prepare_uninterpolated_move_to_destination(); // set_current_to_destination
  1316. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1317. if (DEBUGGING(LEVELING)) DEBUG_POS("z raise move", current_position);
  1318. #endif
  1319. }
  1320. destination[X_AXIS] = x;
  1321. destination[Y_AXIS] = y;
  1322. prepare_move_to_destination(); // set_current_to_destination
  1323. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1324. if (DEBUGGING(LEVELING)) DEBUG_POS("xy move", current_position);
  1325. #endif
  1326. if (z < current_position[Z_AXIS]) { // lowering?
  1327. destination[Z_AXIS] = z;
  1328. prepare_uninterpolated_move_to_destination(); // set_current_to_destination
  1329. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1330. if (DEBUGGING(LEVELING)) DEBUG_POS("z lower move", current_position);
  1331. #endif
  1332. }
  1333. #elif IS_SCARA
  1334. set_destination_to_current();
  1335. // If Z needs to raise, do it before moving XY
  1336. if (destination[Z_AXIS] < z) {
  1337. destination[Z_AXIS] = z;
  1338. prepare_uninterpolated_move_to_destination(fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[Z_AXIS]);
  1339. }
  1340. destination[X_AXIS] = x;
  1341. destination[Y_AXIS] = y;
  1342. prepare_uninterpolated_move_to_destination(fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S);
  1343. // If Z needs to lower, do it after moving XY
  1344. if (destination[Z_AXIS] > z) {
  1345. destination[Z_AXIS] = z;
  1346. prepare_uninterpolated_move_to_destination(fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[Z_AXIS]);
  1347. }
  1348. #else
  1349. // If Z needs to raise, do it before moving XY
  1350. if (current_position[Z_AXIS] < z) {
  1351. feedrate_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[Z_AXIS];
  1352. current_position[Z_AXIS] = z;
  1353. line_to_current_position();
  1354. }
  1355. feedrate_mm_s = fr_mm_s ? fr_mm_s : XY_PROBE_FEEDRATE_MM_S;
  1356. current_position[X_AXIS] = x;
  1357. current_position[Y_AXIS] = y;
  1358. line_to_current_position();
  1359. // If Z needs to lower, do it after moving XY
  1360. if (current_position[Z_AXIS] > z) {
  1361. feedrate_mm_s = fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[Z_AXIS];
  1362. current_position[Z_AXIS] = z;
  1363. line_to_current_position();
  1364. }
  1365. #endif
  1366. stepper.synchronize();
  1367. feedrate_mm_s = old_feedrate_mm_s;
  1368. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1369. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< do_blocking_move_to");
  1370. #endif
  1371. }
  1372. void do_blocking_move_to_x(const float &x, const float &fr_mm_s/*=0.0*/) {
  1373. do_blocking_move_to(x, current_position[Y_AXIS], current_position[Z_AXIS], fr_mm_s);
  1374. }
  1375. void do_blocking_move_to_z(const float &z, const float &fr_mm_s/*=0.0*/) {
  1376. do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], z, fr_mm_s);
  1377. }
  1378. void do_blocking_move_to_xy(const float &x, const float &y, const float &fr_mm_s/*=0.0*/) {
  1379. do_blocking_move_to(x, y, current_position[Z_AXIS], fr_mm_s);
  1380. }
  1381. //
  1382. // Prepare to do endstop or probe moves
  1383. // with custom feedrates.
  1384. //
  1385. // - Save current feedrates
  1386. // - Reset the rate multiplier
  1387. // - Reset the command timeout
  1388. // - Enable the endstops (for endstop moves)
  1389. //
  1390. static void setup_for_endstop_or_probe_move() {
  1391. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1392. if (DEBUGGING(LEVELING)) DEBUG_POS("setup_for_endstop_or_probe_move", current_position);
  1393. #endif
  1394. saved_feedrate_mm_s = feedrate_mm_s;
  1395. saved_feedrate_percentage = feedrate_percentage;
  1396. feedrate_percentage = 100;
  1397. refresh_cmd_timeout();
  1398. }
  1399. static void clean_up_after_endstop_or_probe_move() {
  1400. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1401. if (DEBUGGING(LEVELING)) DEBUG_POS("clean_up_after_endstop_or_probe_move", current_position);
  1402. #endif
  1403. feedrate_mm_s = saved_feedrate_mm_s;
  1404. feedrate_percentage = saved_feedrate_percentage;
  1405. refresh_cmd_timeout();
  1406. }
  1407. #if HAS_BED_PROBE
  1408. /**
  1409. * Raise Z to a minimum height to make room for a probe to move
  1410. */
  1411. inline void do_probe_raise(float z_raise) {
  1412. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1413. if (DEBUGGING(LEVELING)) {
  1414. SERIAL_ECHOPAIR("do_probe_raise(", z_raise);
  1415. SERIAL_ECHOLNPGM(")");
  1416. }
  1417. #endif
  1418. float z_dest = LOGICAL_Z_POSITION(z_raise);
  1419. if (zprobe_zoffset < 0) z_dest -= zprobe_zoffset;
  1420. if (z_dest > current_position[Z_AXIS])
  1421. do_blocking_move_to_z(z_dest);
  1422. }
  1423. #endif //HAS_BED_PROBE
  1424. #if ENABLED(Z_PROBE_ALLEN_KEY) || ENABLED(Z_PROBE_SLED) || HAS_PROBING_PROCEDURE || HOTENDS > 1 || ENABLED(NOZZLE_CLEAN_FEATURE) || ENABLED(NOZZLE_PARK_FEATURE)
  1425. static bool axis_unhomed_error(const bool x, const bool y, const bool z) {
  1426. const bool xx = x && !axis_homed[X_AXIS],
  1427. yy = y && !axis_homed[Y_AXIS],
  1428. zz = z && !axis_homed[Z_AXIS];
  1429. if (xx || yy || zz) {
  1430. SERIAL_ECHO_START;
  1431. SERIAL_ECHOPGM(MSG_HOME " ");
  1432. if (xx) SERIAL_ECHOPGM(MSG_X);
  1433. if (yy) SERIAL_ECHOPGM(MSG_Y);
  1434. if (zz) SERIAL_ECHOPGM(MSG_Z);
  1435. SERIAL_ECHOLNPGM(" " MSG_FIRST);
  1436. #if ENABLED(ULTRA_LCD)
  1437. char message[3 * (LCD_WIDTH) + 1] = ""; // worst case is kana.utf with up to 3*LCD_WIDTH+1
  1438. strcat_P(message, PSTR(MSG_HOME " "));
  1439. if (xx) strcat_P(message, PSTR(MSG_X));
  1440. if (yy) strcat_P(message, PSTR(MSG_Y));
  1441. if (zz) strcat_P(message, PSTR(MSG_Z));
  1442. strcat_P(message, PSTR(" " MSG_FIRST));
  1443. lcd_setstatus(message);
  1444. #endif
  1445. return true;
  1446. }
  1447. return false;
  1448. }
  1449. #endif
  1450. #if ENABLED(Z_PROBE_SLED)
  1451. #ifndef SLED_DOCKING_OFFSET
  1452. #define SLED_DOCKING_OFFSET 0
  1453. #endif
  1454. /**
  1455. * Method to dock/undock a sled designed by Charles Bell.
  1456. *
  1457. * stow[in] If false, move to MAX_X and engage the solenoid
  1458. * If true, move to MAX_X and release the solenoid
  1459. */
  1460. static void dock_sled(bool stow) {
  1461. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1462. if (DEBUGGING(LEVELING)) {
  1463. SERIAL_ECHOPAIR("dock_sled(", stow);
  1464. SERIAL_ECHOLNPGM(")");
  1465. }
  1466. #endif
  1467. // Dock sled a bit closer to ensure proper capturing
  1468. do_blocking_move_to_x(X_MAX_POS + SLED_DOCKING_OFFSET - ((stow) ? 1 : 0));
  1469. #if PIN_EXISTS(SLED)
  1470. digitalWrite(SLED_PIN, !stow); // switch solenoid
  1471. #endif
  1472. }
  1473. #endif // Z_PROBE_SLED
  1474. #if ENABLED(Z_PROBE_ALLEN_KEY)
  1475. void run_deploy_moves_script() {
  1476. #if defined(Z_PROBE_ALLEN_KEY_DEPLOY_1_X) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_1_Y) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_1_Z)
  1477. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_1_X
  1478. #define Z_PROBE_ALLEN_KEY_DEPLOY_1_X current_position[X_AXIS]
  1479. #endif
  1480. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_1_Y
  1481. #define Z_PROBE_ALLEN_KEY_DEPLOY_1_Y current_position[Y_AXIS]
  1482. #endif
  1483. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_1_Z
  1484. #define Z_PROBE_ALLEN_KEY_DEPLOY_1_Z current_position[Z_AXIS]
  1485. #endif
  1486. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE
  1487. #define Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE 0.0
  1488. #endif
  1489. do_blocking_move_to(Z_PROBE_ALLEN_KEY_DEPLOY_1_X, Z_PROBE_ALLEN_KEY_DEPLOY_1_Y, Z_PROBE_ALLEN_KEY_DEPLOY_1_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE));
  1490. #endif
  1491. #if defined(Z_PROBE_ALLEN_KEY_DEPLOY_2_X) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_2_Y) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_2_Z)
  1492. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_2_X
  1493. #define Z_PROBE_ALLEN_KEY_DEPLOY_2_X current_position[X_AXIS]
  1494. #endif
  1495. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_2_Y
  1496. #define Z_PROBE_ALLEN_KEY_DEPLOY_2_Y current_position[Y_AXIS]
  1497. #endif
  1498. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_2_Z
  1499. #define Z_PROBE_ALLEN_KEY_DEPLOY_2_Z current_position[Z_AXIS]
  1500. #endif
  1501. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE
  1502. #define Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE 0.0
  1503. #endif
  1504. do_blocking_move_to(Z_PROBE_ALLEN_KEY_DEPLOY_2_X, Z_PROBE_ALLEN_KEY_DEPLOY_2_Y, Z_PROBE_ALLEN_KEY_DEPLOY_2_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE));
  1505. #endif
  1506. #if defined(Z_PROBE_ALLEN_KEY_DEPLOY_3_X) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_3_Y) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_3_Z)
  1507. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_3_X
  1508. #define Z_PROBE_ALLEN_KEY_DEPLOY_3_X current_position[X_AXIS]
  1509. #endif
  1510. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_3_Y
  1511. #define Z_PROBE_ALLEN_KEY_DEPLOY_3_Y current_position[Y_AXIS]
  1512. #endif
  1513. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_3_Z
  1514. #define Z_PROBE_ALLEN_KEY_DEPLOY_3_Z current_position[Z_AXIS]
  1515. #endif
  1516. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE
  1517. #define Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE 0.0
  1518. #endif
  1519. do_blocking_move_to(Z_PROBE_ALLEN_KEY_DEPLOY_3_X, Z_PROBE_ALLEN_KEY_DEPLOY_3_Y, Z_PROBE_ALLEN_KEY_DEPLOY_3_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE));
  1520. #endif
  1521. #if defined(Z_PROBE_ALLEN_KEY_DEPLOY_4_X) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_4_Y) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_4_Z)
  1522. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_4_X
  1523. #define Z_PROBE_ALLEN_KEY_DEPLOY_4_X current_position[X_AXIS]
  1524. #endif
  1525. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_4_Y
  1526. #define Z_PROBE_ALLEN_KEY_DEPLOY_4_Y current_position[Y_AXIS]
  1527. #endif
  1528. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_4_Z
  1529. #define Z_PROBE_ALLEN_KEY_DEPLOY_4_Z current_position[Z_AXIS]
  1530. #endif
  1531. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE
  1532. #define Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE 0.0
  1533. #endif
  1534. do_blocking_move_to(Z_PROBE_ALLEN_KEY_DEPLOY_4_X, Z_PROBE_ALLEN_KEY_DEPLOY_4_Y, Z_PROBE_ALLEN_KEY_DEPLOY_4_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_4_FEEDRATE));
  1535. #endif
  1536. #if defined(Z_PROBE_ALLEN_KEY_DEPLOY_5_X) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_5_Y) || defined(Z_PROBE_ALLEN_KEY_DEPLOY_5_Z)
  1537. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_5_X
  1538. #define Z_PROBE_ALLEN_KEY_DEPLOY_5_X current_position[X_AXIS]
  1539. #endif
  1540. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_5_Y
  1541. #define Z_PROBE_ALLEN_KEY_DEPLOY_5_Y current_position[Y_AXIS]
  1542. #endif
  1543. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_5_Z
  1544. #define Z_PROBE_ALLEN_KEY_DEPLOY_5_Z current_position[Z_AXIS]
  1545. #endif
  1546. #ifndef Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE
  1547. #define Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE 0.0
  1548. #endif
  1549. do_blocking_move_to(Z_PROBE_ALLEN_KEY_DEPLOY_5_X, Z_PROBE_ALLEN_KEY_DEPLOY_5_Y, Z_PROBE_ALLEN_KEY_DEPLOY_5_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_DEPLOY_5_FEEDRATE));
  1550. #endif
  1551. }
  1552. void run_stow_moves_script() {
  1553. #if defined(Z_PROBE_ALLEN_KEY_STOW_1_X) || defined(Z_PROBE_ALLEN_KEY_STOW_1_Y) || defined(Z_PROBE_ALLEN_KEY_STOW_1_Z)
  1554. #ifndef Z_PROBE_ALLEN_KEY_STOW_1_X
  1555. #define Z_PROBE_ALLEN_KEY_STOW_1_X current_position[X_AXIS]
  1556. #endif
  1557. #ifndef Z_PROBE_ALLEN_KEY_STOW_1_Y
  1558. #define Z_PROBE_ALLEN_KEY_STOW_1_Y current_position[Y_AXIS]
  1559. #endif
  1560. #ifndef Z_PROBE_ALLEN_KEY_STOW_1_Z
  1561. #define Z_PROBE_ALLEN_KEY_STOW_1_Z current_position[Z_AXIS]
  1562. #endif
  1563. #ifndef Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE
  1564. #define Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE 0.0
  1565. #endif
  1566. do_blocking_move_to(Z_PROBE_ALLEN_KEY_STOW_1_X, Z_PROBE_ALLEN_KEY_STOW_1_Y, Z_PROBE_ALLEN_KEY_STOW_1_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE));
  1567. #endif
  1568. #if defined(Z_PROBE_ALLEN_KEY_STOW_2_X) || defined(Z_PROBE_ALLEN_KEY_STOW_2_Y) || defined(Z_PROBE_ALLEN_KEY_STOW_2_Z)
  1569. #ifndef Z_PROBE_ALLEN_KEY_STOW_2_X
  1570. #define Z_PROBE_ALLEN_KEY_STOW_2_X current_position[X_AXIS]
  1571. #endif
  1572. #ifndef Z_PROBE_ALLEN_KEY_STOW_2_Y
  1573. #define Z_PROBE_ALLEN_KEY_STOW_2_Y current_position[Y_AXIS]
  1574. #endif
  1575. #ifndef Z_PROBE_ALLEN_KEY_STOW_2_Z
  1576. #define Z_PROBE_ALLEN_KEY_STOW_2_Z current_position[Z_AXIS]
  1577. #endif
  1578. #ifndef Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE
  1579. #define Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE 0.0
  1580. #endif
  1581. do_blocking_move_to(Z_PROBE_ALLEN_KEY_STOW_2_X, Z_PROBE_ALLEN_KEY_STOW_2_Y, Z_PROBE_ALLEN_KEY_STOW_2_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE));
  1582. #endif
  1583. #if defined(Z_PROBE_ALLEN_KEY_STOW_3_X) || defined(Z_PROBE_ALLEN_KEY_STOW_3_Y) || defined(Z_PROBE_ALLEN_KEY_STOW_3_Z)
  1584. #ifndef Z_PROBE_ALLEN_KEY_STOW_3_X
  1585. #define Z_PROBE_ALLEN_KEY_STOW_3_X current_position[X_AXIS]
  1586. #endif
  1587. #ifndef Z_PROBE_ALLEN_KEY_STOW_3_Y
  1588. #define Z_PROBE_ALLEN_KEY_STOW_3_Y current_position[Y_AXIS]
  1589. #endif
  1590. #ifndef Z_PROBE_ALLEN_KEY_STOW_3_Z
  1591. #define Z_PROBE_ALLEN_KEY_STOW_3_Z current_position[Z_AXIS]
  1592. #endif
  1593. #ifndef Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE
  1594. #define Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE 0.0
  1595. #endif
  1596. do_blocking_move_to(Z_PROBE_ALLEN_KEY_STOW_3_X, Z_PROBE_ALLEN_KEY_STOW_3_Y, Z_PROBE_ALLEN_KEY_STOW_3_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE));
  1597. #endif
  1598. #if defined(Z_PROBE_ALLEN_KEY_STOW_4_X) || defined(Z_PROBE_ALLEN_KEY_STOW_4_Y) || defined(Z_PROBE_ALLEN_KEY_STOW_4_Z)
  1599. #ifndef Z_PROBE_ALLEN_KEY_STOW_4_X
  1600. #define Z_PROBE_ALLEN_KEY_STOW_4_X current_position[X_AXIS]
  1601. #endif
  1602. #ifndef Z_PROBE_ALLEN_KEY_STOW_4_Y
  1603. #define Z_PROBE_ALLEN_KEY_STOW_4_Y current_position[Y_AXIS]
  1604. #endif
  1605. #ifndef Z_PROBE_ALLEN_KEY_STOW_4_Z
  1606. #define Z_PROBE_ALLEN_KEY_STOW_4_Z current_position[Z_AXIS]
  1607. #endif
  1608. #ifndef Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE
  1609. #define Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE 0.0
  1610. #endif
  1611. do_blocking_move_to(Z_PROBE_ALLEN_KEY_STOW_4_X, Z_PROBE_ALLEN_KEY_STOW_4_Y, Z_PROBE_ALLEN_KEY_STOW_4_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE));
  1612. #endif
  1613. #if defined(Z_PROBE_ALLEN_KEY_STOW_5_X) || defined(Z_PROBE_ALLEN_KEY_STOW_5_Y) || defined(Z_PROBE_ALLEN_KEY_STOW_5_Z)
  1614. #ifndef Z_PROBE_ALLEN_KEY_STOW_5_X
  1615. #define Z_PROBE_ALLEN_KEY_STOW_5_X current_position[X_AXIS]
  1616. #endif
  1617. #ifndef Z_PROBE_ALLEN_KEY_STOW_5_Y
  1618. #define Z_PROBE_ALLEN_KEY_STOW_5_Y current_position[Y_AXIS]
  1619. #endif
  1620. #ifndef Z_PROBE_ALLEN_KEY_STOW_5_Z
  1621. #define Z_PROBE_ALLEN_KEY_STOW_5_Z current_position[Z_AXIS]
  1622. #endif
  1623. #ifndef Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE
  1624. #define Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE 0.0
  1625. #endif
  1626. do_blocking_move_to(Z_PROBE_ALLEN_KEY_STOW_5_X, Z_PROBE_ALLEN_KEY_STOW_5_Y, Z_PROBE_ALLEN_KEY_STOW_5_Z, MMM_TO_MMS(Z_PROBE_ALLEN_KEY_STOW_5_FEEDRATE));
  1627. #endif
  1628. }
  1629. #endif
  1630. #if HAS_BED_PROBE
  1631. // TRIGGERED_WHEN_STOWED_TEST can easily be extended to servo probes, ... if needed.
  1632. #if ENABLED(PROBE_IS_TRIGGERED_WHEN_STOWED_TEST)
  1633. #if ENABLED(Z_MIN_PROBE_ENDSTOP)
  1634. #define _TRIGGERED_WHEN_STOWED_TEST (READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING)
  1635. #else
  1636. #define _TRIGGERED_WHEN_STOWED_TEST (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING)
  1637. #endif
  1638. #endif
  1639. #define DEPLOY_PROBE() set_probe_deployed(true)
  1640. #define STOW_PROBE() set_probe_deployed(false)
  1641. #if ENABLED(BLTOUCH)
  1642. FORCE_INLINE void set_bltouch_deployed(const bool &deploy) {
  1643. servo[Z_ENDSTOP_SERVO_NR].move(deploy ? BLTOUCH_DEPLOY : BLTOUCH_STOW);
  1644. }
  1645. #endif
  1646. // returns false for ok and true for failure
  1647. static bool set_probe_deployed(bool deploy) {
  1648. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1649. if (DEBUGGING(LEVELING)) {
  1650. DEBUG_POS("set_probe_deployed", current_position);
  1651. SERIAL_ECHOLNPAIR("deploy: ", deploy);
  1652. }
  1653. #endif
  1654. if (endstops.z_probe_enabled == deploy) return false;
  1655. // Make room for probe
  1656. do_probe_raise(_Z_CLEARANCE_DEPLOY_PROBE);
  1657. // When deploying make sure BLTOUCH is not already triggered
  1658. #if ENABLED(BLTOUCH)
  1659. if (deploy && TEST_BLTOUCH()) { stop(); return true; }
  1660. #endif
  1661. #if ENABLED(Z_PROBE_SLED)
  1662. if (axis_unhomed_error(true, false, false)) { stop(); return true; }
  1663. #elif ENABLED(Z_PROBE_ALLEN_KEY)
  1664. if (axis_unhomed_error(true, true, true )) { stop(); return true; }
  1665. #endif
  1666. float oldXpos = current_position[X_AXIS],
  1667. oldYpos = current_position[Y_AXIS];
  1668. #ifdef _TRIGGERED_WHEN_STOWED_TEST
  1669. // If endstop is already false, the Z probe is deployed
  1670. if (_TRIGGERED_WHEN_STOWED_TEST == deploy) { // closed after the probe specific actions.
  1671. // Would a goto be less ugly?
  1672. //while (!_TRIGGERED_WHEN_STOWED_TEST) idle(); // would offer the opportunity
  1673. // for a triggered when stowed manual probe.
  1674. if (!deploy) endstops.enable_z_probe(false); // Switch off triggered when stowed probes early
  1675. // otherwise an Allen-Key probe can't be stowed.
  1676. #endif
  1677. #if ENABLED(Z_PROBE_SLED)
  1678. dock_sled(!deploy);
  1679. #elif HAS_Z_SERVO_ENDSTOP && DISABLED(BLTOUCH)
  1680. servo[Z_ENDSTOP_SERVO_NR].move(z_servo_angle[deploy ? 0 : 1]);
  1681. #elif ENABLED(Z_PROBE_ALLEN_KEY)
  1682. deploy ? run_deploy_moves_script() : run_stow_moves_script();
  1683. #endif
  1684. #ifdef _TRIGGERED_WHEN_STOWED_TEST
  1685. } // _TRIGGERED_WHEN_STOWED_TEST == deploy
  1686. if (_TRIGGERED_WHEN_STOWED_TEST == deploy) { // State hasn't changed?
  1687. if (IsRunning()) {
  1688. SERIAL_ERROR_START;
  1689. SERIAL_ERRORLNPGM("Z-Probe failed");
  1690. LCD_ALERTMESSAGEPGM("Err: ZPROBE");
  1691. }
  1692. stop();
  1693. return true;
  1694. } // _TRIGGERED_WHEN_STOWED_TEST == deploy
  1695. #endif
  1696. do_blocking_move_to(oldXpos, oldYpos, current_position[Z_AXIS]); // return to position before deploy
  1697. endstops.enable_z_probe(deploy);
  1698. return false;
  1699. }
  1700. static void do_probe_move(float z, float fr_mm_m) {
  1701. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1702. if (DEBUGGING(LEVELING)) DEBUG_POS(">>> do_probe_move", current_position);
  1703. #endif
  1704. // Deploy BLTouch at the start of any probe
  1705. #if ENABLED(BLTOUCH)
  1706. set_bltouch_deployed(true);
  1707. #endif
  1708. // Move down until probe triggered
  1709. do_blocking_move_to_z(LOGICAL_Z_POSITION(z), MMM_TO_MMS(fr_mm_m));
  1710. // Retract BLTouch immediately after a probe
  1711. #if ENABLED(BLTOUCH)
  1712. set_bltouch_deployed(false);
  1713. #endif
  1714. // Clear endstop flags
  1715. endstops.hit_on_purpose();
  1716. // Tell the planner where we actually are
  1717. planner.sync_from_steppers();
  1718. // Get Z where the steppers were interrupted
  1719. set_current_from_steppers_for_axis(Z_AXIS);
  1720. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1721. if (DEBUGGING(LEVELING)) DEBUG_POS("<<< do_probe_move", current_position);
  1722. #endif
  1723. }
  1724. // Do a single Z probe and return with current_position[Z_AXIS]
  1725. // at the height where the probe triggered.
  1726. static float run_z_probe() {
  1727. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1728. if (DEBUGGING(LEVELING)) DEBUG_POS(">>> run_z_probe", current_position);
  1729. #endif
  1730. // Prevent stepper_inactive_time from running out and EXTRUDER_RUNOUT_PREVENT from extruding
  1731. refresh_cmd_timeout();
  1732. #if ENABLED(PROBE_DOUBLE_TOUCH)
  1733. // Do a first probe at the fast speed
  1734. do_probe_move(-(Z_MAX_LENGTH) - 10, Z_PROBE_SPEED_FAST);
  1735. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1736. float first_probe_z = current_position[Z_AXIS];
  1737. if (DEBUGGING(LEVELING))
  1738. SERIAL_ECHOPAIR("1st Probe Z:", first_probe_z);
  1739. #endif
  1740. // move up by the bump distance
  1741. do_blocking_move_to_z(current_position[Z_AXIS] + home_bump_mm(Z_AXIS), MMM_TO_MMS(Z_PROBE_SPEED_FAST));
  1742. #else
  1743. // If the nozzle is above the travel height then
  1744. // move down quickly before doing the slow probe
  1745. float z = LOGICAL_Z_POSITION(Z_CLEARANCE_BETWEEN_PROBES);
  1746. if (z < current_position[Z_AXIS])
  1747. do_blocking_move_to_z(z, MMM_TO_MMS(Z_PROBE_SPEED_FAST));
  1748. #endif
  1749. // move down slowly to find bed
  1750. do_probe_move(-(Z_MAX_LENGTH) - 10, Z_PROBE_SPEED_SLOW);
  1751. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1752. if (DEBUGGING(LEVELING)) DEBUG_POS("<<< run_z_probe", current_position);
  1753. #endif
  1754. // Debug: compare probe heights
  1755. #if ENABLED(PROBE_DOUBLE_TOUCH) && ENABLED(DEBUG_LEVELING_FEATURE)
  1756. if (DEBUGGING(LEVELING)) {
  1757. SERIAL_ECHOPAIR("2nd Probe Z:", current_position[Z_AXIS]);
  1758. SERIAL_ECHOLNPAIR(" Discrepancy:", first_probe_z - current_position[Z_AXIS]);
  1759. }
  1760. #endif
  1761. return current_position[Z_AXIS];
  1762. }
  1763. //
  1764. // - Move to the given XY
  1765. // - Deploy the probe, if not already deployed
  1766. // - Probe the bed, get the Z position
  1767. // - Depending on the 'stow' flag
  1768. // - Stow the probe, or
  1769. // - Raise to the BETWEEN height
  1770. // - Return the probed Z position
  1771. //
  1772. static float probe_pt(const float &x, const float &y, bool stow = true, int verbose_level = 1) {
  1773. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1774. if (DEBUGGING(LEVELING)) {
  1775. SERIAL_ECHOPAIR(">>> probe_pt(", x);
  1776. SERIAL_ECHOPAIR(", ", y);
  1777. SERIAL_ECHOPAIR(", ", stow ? "stow" : "no stow");
  1778. SERIAL_ECHOLNPGM(")");
  1779. DEBUG_POS("", current_position);
  1780. }
  1781. #endif
  1782. float old_feedrate_mm_s = feedrate_mm_s;
  1783. // Ensure a minimum height before moving the probe
  1784. do_probe_raise(Z_CLEARANCE_BETWEEN_PROBES);
  1785. // Move to the XY where we shall probe
  1786. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1787. if (DEBUGGING(LEVELING)) {
  1788. SERIAL_ECHOPAIR("> do_blocking_move_to_xy(", x - (X_PROBE_OFFSET_FROM_EXTRUDER));
  1789. SERIAL_ECHOPAIR(", ", y - (Y_PROBE_OFFSET_FROM_EXTRUDER));
  1790. SERIAL_ECHOLNPGM(")");
  1791. }
  1792. #endif
  1793. feedrate_mm_s = XY_PROBE_FEEDRATE_MM_S;
  1794. // Move the probe to the given XY
  1795. do_blocking_move_to_xy(x - (X_PROBE_OFFSET_FROM_EXTRUDER), y - (Y_PROBE_OFFSET_FROM_EXTRUDER));
  1796. if (DEPLOY_PROBE()) return NAN;
  1797. float measured_z = run_z_probe();
  1798. if (!stow)
  1799. do_probe_raise(Z_CLEARANCE_BETWEEN_PROBES);
  1800. else
  1801. if (STOW_PROBE()) return NAN;
  1802. if (verbose_level > 2) {
  1803. SERIAL_PROTOCOLPGM("Bed X: ");
  1804. SERIAL_PROTOCOL_F(x, 3);
  1805. SERIAL_PROTOCOLPGM(" Y: ");
  1806. SERIAL_PROTOCOL_F(y, 3);
  1807. SERIAL_PROTOCOLPGM(" Z: ");
  1808. SERIAL_PROTOCOL_F(measured_z, 3);
  1809. SERIAL_EOL;
  1810. }
  1811. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1812. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< probe_pt");
  1813. #endif
  1814. feedrate_mm_s = old_feedrate_mm_s;
  1815. return measured_z;
  1816. }
  1817. #endif // HAS_BED_PROBE
  1818. #if PLANNER_LEVELING
  1819. /**
  1820. * Turn bed leveling on or off, fixing the current
  1821. * position as-needed.
  1822. *
  1823. * Disable: Current position = physical position
  1824. * Enable: Current position = "unleveled" physical position
  1825. */
  1826. void set_bed_leveling_enabled(bool enable=true) {
  1827. #if ENABLED(MESH_BED_LEVELING)
  1828. if (!enable && mbl.active())
  1829. current_position[Z_AXIS] +=
  1830. mbl.get_z(RAW_CURRENT_POSITION(X_AXIS), RAW_CURRENT_POSITION(Y_AXIS)) - (MESH_HOME_SEARCH_Z);
  1831. mbl.set_active(enable && mbl.has_mesh()); // was set_has_mesh(). Is this not correct?
  1832. #elif HAS_ABL
  1833. if (enable != planner.abl_enabled) {
  1834. planner.abl_enabled = !planner.abl_enabled;
  1835. if (!planner.abl_enabled)
  1836. set_current_from_steppers_for_axis(
  1837. #if ABL_PLANAR
  1838. ALL_AXES
  1839. #else
  1840. Z_AXIS
  1841. #endif
  1842. );
  1843. else
  1844. planner.unapply_leveling(current_position);
  1845. }
  1846. #endif
  1847. }
  1848. /**
  1849. * Reset calibration results to zero.
  1850. */
  1851. void reset_bed_level() {
  1852. #if ENABLED(MESH_BED_LEVELING)
  1853. if (mbl.has_mesh()) {
  1854. set_bed_leveling_enabled(false);
  1855. mbl.reset();
  1856. mbl.set_has_mesh(false);
  1857. }
  1858. #else
  1859. planner.abl_enabled = false;
  1860. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1861. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level");
  1862. #endif
  1863. #if ABL_PLANAR
  1864. planner.bed_level_matrix.set_to_identity();
  1865. #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
  1866. for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++)
  1867. for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++)
  1868. bed_level_grid[x][y] = 1000.0;
  1869. #endif
  1870. #endif
  1871. }
  1872. #endif // PLANNER_LEVELING
  1873. #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
  1874. /**
  1875. * Extrapolate a single point from its neighbors
  1876. */
  1877. static void extrapolate_one_point(uint8_t x, uint8_t y, int8_t xdir, int8_t ydir) {
  1878. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1879. if (DEBUGGING(LEVELING)) {
  1880. SERIAL_ECHOPGM("Extrapolate [");
  1881. if (x < 10) SERIAL_CHAR(' ');
  1882. SERIAL_ECHO((int)x);
  1883. SERIAL_CHAR(xdir ? (xdir > 0 ? '+' : '-') : ' ');
  1884. SERIAL_CHAR(' ');
  1885. if (y < 10) SERIAL_CHAR(' ');
  1886. SERIAL_ECHO((int)y);
  1887. SERIAL_CHAR(ydir ? (ydir > 0 ? '+' : '-') : ' ');
  1888. SERIAL_ECHOLN(']');
  1889. }
  1890. #endif
  1891. if (bed_level_grid[x][y] < 999.0) {
  1892. #if ENABLED(DEBUG_LEVELING_FEATURE)
  1893. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM(" (done)");
  1894. #endif
  1895. return; // Don't overwrite good values.
  1896. }
  1897. // Get X neighbors, Y neighbors, and XY neighbors
  1898. float a1 = bed_level_grid[x + xdir][y], a2 = bed_level_grid[x + xdir * 2][y],
  1899. b1 = bed_level_grid[x][y + ydir], b2 = bed_level_grid[x][y + ydir * 2],
  1900. c1 = bed_level_grid[x + xdir][y + ydir], c2 = bed_level_grid[x + xdir * 2][y + ydir * 2];
  1901. // Treat far unprobed points as zero, near as equal to far
  1902. if (a2 > 999.0) a2 = 0.0; if (a1 > 999.0) a1 = a2;
  1903. if (b2 > 999.0) b2 = 0.0; if (b1 > 999.0) b1 = b2;
  1904. if (c2 > 999.0) c2 = 0.0; if (c1 > 999.0) c1 = c2;
  1905. float a = 2 * a1 - a2, b = 2 * b1 - b2, c = 2 * c1 - c2;
  1906. // Take the average intstead of the median
  1907. bed_level_grid[x][y] = (a + b + c) / 3.0;
  1908. // Median is robust (ignores outliers).
  1909. // bed_level_grid[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
  1910. // : ((c < b) ? b : (a < c) ? a : c);
  1911. }
  1912. #define EXTRAPOLATE_FROM_EDGE
  1913. #if ENABLED(EXTRAPOLATE_FROM_EDGE)
  1914. #if ABL_GRID_POINTS_X < ABL_GRID_POINTS_Y
  1915. #define HALF_IN_X
  1916. #elif ABL_GRID_POINTS_Y < ABL_GRID_POINTS_X
  1917. #define HALF_IN_Y
  1918. #endif
  1919. #endif
  1920. /**
  1921. * Fill in the unprobed points (corners of circular print surface)
  1922. * using linear extrapolation, away from the center.
  1923. */
  1924. static void extrapolate_unprobed_bed_level() {
  1925. #ifdef HALF_IN_X
  1926. const uint8_t ctrx2 = 0, xlen = ABL_GRID_POINTS_X - 1;
  1927. #else
  1928. const uint8_t ctrx1 = (ABL_GRID_POINTS_X - 1) / 2, // left-of-center
  1929. ctrx2 = ABL_GRID_POINTS_X / 2, // right-of-center
  1930. xlen = ctrx1;
  1931. #endif
  1932. #ifdef HALF_IN_Y
  1933. const uint8_t ctry2 = 0, ylen = ABL_GRID_POINTS_Y - 1;
  1934. #else
  1935. const uint8_t ctry1 = (ABL_GRID_POINTS_Y - 1) / 2, // top-of-center
  1936. ctry2 = ABL_GRID_POINTS_Y / 2, // bottom-of-center
  1937. ylen = ctry1;
  1938. #endif
  1939. for (uint8_t xo = 0; xo <= xlen; xo++)
  1940. for (uint8_t yo = 0; yo <= ylen; yo++) {
  1941. uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo;
  1942. #ifndef HALF_IN_X
  1943. uint8_t x1 = ctrx1 - xo;
  1944. #endif
  1945. #ifndef HALF_IN_Y
  1946. uint8_t y1 = ctry1 - yo;
  1947. #ifndef HALF_IN_X
  1948. extrapolate_one_point(x1, y1, +1, +1); // left-below + +
  1949. #endif
  1950. extrapolate_one_point(x2, y1, -1, +1); // right-below - +
  1951. #endif
  1952. #ifndef HALF_IN_X
  1953. extrapolate_one_point(x1, y2, +1, -1); // left-above + -
  1954. #endif
  1955. extrapolate_one_point(x2, y2, -1, -1); // right-above - -
  1956. }
  1957. }
  1958. /**
  1959. * Print calibration results for plotting or manual frame adjustment.
  1960. */
  1961. static void print_bed_level() {
  1962. SERIAL_ECHOPGM("Bilinear Leveling Grid:\n ");
  1963. for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) {
  1964. SERIAL_PROTOCOLPGM(" ");
  1965. if (x < 10) SERIAL_PROTOCOLCHAR(' ');
  1966. SERIAL_PROTOCOL((int)x);
  1967. }
  1968. SERIAL_EOL;
  1969. for (uint8_t y = 0; y < ABL_GRID_POINTS_Y; y++) {
  1970. if (y < 9) SERIAL_PROTOCOLCHAR(' ');
  1971. SERIAL_PROTOCOL(y);
  1972. for (uint8_t x = 0; x < ABL_GRID_POINTS_X; x++) {
  1973. SERIAL_PROTOCOLCHAR(' ');
  1974. float offset = bed_level_grid[x][y];
  1975. if (offset < 999.0) {
  1976. if (offset > 0) SERIAL_CHAR('+');
  1977. SERIAL_PROTOCOL_F(offset, 2);
  1978. }
  1979. else
  1980. SERIAL_PROTOCOLPGM(" ====");
  1981. }
  1982. SERIAL_EOL;
  1983. }
  1984. SERIAL_EOL;
  1985. }
  1986. #endif // AUTO_BED_LEVELING_BILINEAR
  1987. #ifdef G38_2_3
  1988. #define G38_minimum_move 0.0275 // minimum distance in mm that will produce a move (determined using the print statement in check_move)
  1989. bool check_move() //checks that at least one of the axis in the command line has an actual move
  1990. // motion planner only does moves of 0.001mm and larger
  1991. {
  1992. bool move_flag = false;
  1993. for(int8_t i=0; i < 3; i++) {
  1994. /* debug used to determine prints
  1995. SERIAL_PROTOCOLPGM("axis: ");
  1996. SERIAL_PROTOCOL(axis_codes[i]);
  1997. SERIAL_PROTOCOLPGM(" code_seen : ");
  1998. SERIAL_PROTOCOL(code_seen(axis_codes[i]));
  1999. SERIAL_PROTOCOLPGM(" destination : ");
  2000. SERIAL_PROTOCOL(destination[i]);
  2001. SERIAL_PROTOCOLPGM(" current : ");
  2002. SERIAL_PROTOCOL(current_position[i]);
  2003. SERIAL_PROTOCOLPGM(" dif x 1000 : ");
  2004. SERIAL_PROTOCOLLN((destination[i] - current_position[i]) * 1000);
  2005. */
  2006. if (code_seen(axis_codes[i]) && (fabs(destination[i] - current_position[i]) >= G38_minimum_move)) move_flag = true ;
  2007. /*
  2008. ?? 0.0275mm produced a move on my machine along with an updated current position.
  2009. 0.0265mm did NOT produce a move and did NOT change the current position
  2010. this is very different than the 0.001 in the planner.
  2011. 0.001" is .0254mm so maybe the 0.0275 observed comes from digital storage limitations/conversion/rounding
  2012. */
  2013. }
  2014. return move_flag;
  2015. }
  2016. static void G38_run_probe(bool *G38_pass_fail) {
  2017. G38_flag = true; //tell the interrupt handler that we're doing a G38 probe
  2018. *G38_pass_fail = false;
  2019. #ifdef X_HOME_BUMP_MM
  2020. #ifdef Y_HOME_BUMP_MM
  2021. #ifdef Z_HOME_BUMP_MM
  2022. float G38_X_retract_mm = home_bump_mm(X_AXIS);
  2023. float G38_Y_retract_mm = home_bump_mm(Y_AXIS);
  2024. float G38_Z_retract_mm = home_bump_mm(Z_AXIS);
  2025. #else
  2026. float G38_X_retract_mm = 5;
  2027. float G38_Y_retract_mm = 5;
  2028. float G38_Z_retract_mm = 2;
  2029. #endif
  2030. #endif
  2031. #endif
  2032. // only retract the axis if the axis is in the command
  2033. if( (!code_seen('X') || (code_value_axis_units(X_AXIS) == 0))) G38_X_retract_mm = 0;
  2034. if( (!code_seen('Y') || (code_value_axis_units(Y_AXIS) == 0))) G38_Y_retract_mm = 0;
  2035. if( (!code_seen('Z') || (code_value_axis_units(Z_AXIS) == 0))) G38_Z_retract_mm = 0;
  2036. // change the direction of the retract if needed
  2037. if ((destination[X_AXIS] - current_position[X_AXIS])>0) G38_X_retract_mm = -G38_X_retract_mm;
  2038. if ((destination[Y_AXIS] - current_position[Y_AXIS])>0) G38_Y_retract_mm = -G38_Y_retract_mm;
  2039. if ((destination[Z_AXIS] - current_position[Z_AXIS])>0) G38_Z_retract_mm = -G38_Z_retract_mm;
  2040. stepper.synchronize(); // wait until the machine is idle
  2041. bool save_endstops = endstops.enabled; //remember state of endstops so we can retore them at the end
  2042. endstops.enable(true);
  2043. // move until you reach the destination or hit an endstop or hit the target
  2044. // it's an error unless have hit the target
  2045. G38_flag_pass = false;
  2046. *G38_pass_fail = false;
  2047. planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate_mm_s, active_extruder);
  2048. stepper.synchronize();
  2049. // we have to let the planner know where we are right now as it is not where we said to go.
  2050. // and we need to update current_position[axis]
  2051. current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
  2052. current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
  2053. current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
  2054. planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
  2055. *G38_pass_fail = G38_flag_pass ; // only care if hit target on the first move
  2056. if (*G38_pass_fail) { // no sense in doing the remaining moves if we didn't hit the endstop
  2057. // move away the retract distance
  2058. float xPosition = current_position[X_AXIS] + G38_X_retract_mm;
  2059. float yPosition = current_position[Y_AXIS] + G38_Y_retract_mm;
  2060. float zPosition = current_position[Z_AXIS] + G38_Z_retract_mm;
  2061. // disable endstops on retract otherwise sometimes can't get away
  2062. endstops.enable(false);
  2063. G38_flag = false;
  2064. planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
  2065. stepper.synchronize();
  2066. // move back slowly
  2067. xPosition -= G38_X_retract_mm * 2;
  2068. yPosition -= G38_Y_retract_mm * 2;
  2069. zPosition -= G38_Z_retract_mm * 2;
  2070. // enable endstops on move back
  2071. endstops.enable(true);
  2072. G38_flag = true;
  2073. planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
  2074. stepper.synchronize();
  2075. // we have to let the planner know where we are right now as it is not where we said to go.
  2076. // and we need to update current_position[axis]
  2077. current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
  2078. current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
  2079. current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
  2080. planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
  2081. }
  2082. // clean_up_after_endstop_move();
  2083. endstops.enable(save_endstops); //restore endstops to same state as when we started
  2084. endstops.hit_on_purpose();
  2085. G38_flag = false; //tell the interrupt handler that we're done
  2086. }
  2087. #endif //G38_2_3
  2088. /**
  2089. * Home an individual linear axis
  2090. */
  2091. static void do_homing_move(const AxisEnum axis, float distance, float fr_mm_s=0.0) {
  2092. #if HOMING_Z_WITH_PROBE && ENABLED(BLTOUCH)
  2093. bool deploy_bltouch = (axis == Z_AXIS && distance < 0);
  2094. if (deploy_bltouch) set_bltouch_deployed(true);
  2095. #endif
  2096. // Tell the planner we're at Z=0
  2097. current_position[axis] = 0;
  2098. #if IS_SCARA
  2099. SYNC_PLAN_POSITION_KINEMATIC();
  2100. current_position[axis] = distance;
  2101. inverse_kinematics(current_position);
  2102. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], current_position[E_AXIS], fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[axis], active_extruder);
  2103. #else
  2104. sync_plan_position();
  2105. current_position[axis] = distance;
  2106. planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], fr_mm_s ? fr_mm_s : homing_feedrate_mm_s[axis], active_extruder);
  2107. #endif
  2108. stepper.synchronize();
  2109. #if HOMING_Z_WITH_PROBE && ENABLED(BLTOUCH)
  2110. if (deploy_bltouch) set_bltouch_deployed(false);
  2111. #endif
  2112. endstops.hit_on_purpose();
  2113. }
  2114. /**
  2115. * Home an individual "raw axis" to its endstop.
  2116. * This applies to XYZ on Cartesian and Core robots, and
  2117. * to the individual ABC steppers on DELTA and SCARA.
  2118. *
  2119. * At the end of the procedure the axis is marked as
  2120. * homed and the current position of that axis is updated.
  2121. * Kinematic robots should wait till all axes are homed
  2122. * before updating the current position.
  2123. */
  2124. #define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS)
  2125. static void homeaxis(AxisEnum axis) {
  2126. #if IS_SCARA
  2127. // Only Z homing (with probe) is permitted
  2128. if (axis != Z_AXIS) { BUZZ(100, 880); return; }
  2129. #else
  2130. #define CAN_HOME(A) \
  2131. (axis == A##_AXIS && ((A##_MIN_PIN > -1 && A##_HOME_DIR < 0) || (A##_MAX_PIN > -1 && A##_HOME_DIR > 0)))
  2132. if (!CAN_HOME(X) && !CAN_HOME(Y) && !CAN_HOME(Z)) return;
  2133. #endif
  2134. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2135. if (DEBUGGING(LEVELING)) {
  2136. SERIAL_ECHOPAIR(">>> homeaxis(", axis_codes[axis]);
  2137. SERIAL_ECHOLNPGM(")");
  2138. }
  2139. #endif
  2140. int axis_home_dir =
  2141. #if ENABLED(DUAL_X_CARRIAGE)
  2142. (axis == X_AXIS) ? x_home_dir(active_extruder) :
  2143. #endif
  2144. home_dir(axis);
  2145. // Homing Z towards the bed? Deploy the Z probe or endstop.
  2146. #if HOMING_Z_WITH_PROBE
  2147. if (axis == Z_AXIS && DEPLOY_PROBE()) return;
  2148. #endif
  2149. // Set a flag for Z motor locking
  2150. #if ENABLED(Z_DUAL_ENDSTOPS)
  2151. if (axis == Z_AXIS) stepper.set_homing_flag(true);
  2152. #endif
  2153. // Fast move towards endstop until triggered
  2154. do_homing_move(axis, 1.5 * max_length(axis) * axis_home_dir);
  2155. // When homing Z with probe respect probe clearance
  2156. const float bump = axis_home_dir * (
  2157. #if HOMING_Z_WITH_PROBE
  2158. (axis == Z_AXIS) ? max(Z_CLEARANCE_BETWEEN_PROBES, home_bump_mm(Z_AXIS)) :
  2159. #endif
  2160. home_bump_mm(axis)
  2161. );
  2162. // If a second homing move is configured...
  2163. if (bump) {
  2164. // Move away from the endstop by the axis HOME_BUMP_MM
  2165. do_homing_move(axis, -bump);
  2166. // Slow move towards endstop until triggered
  2167. do_homing_move(axis, 2 * bump, get_homing_bump_feedrate(axis));
  2168. }
  2169. #if ENABLED(Z_DUAL_ENDSTOPS)
  2170. if (axis == Z_AXIS) {
  2171. float adj = fabs(z_endstop_adj);
  2172. bool lockZ1;
  2173. if (axis_home_dir > 0) {
  2174. adj = -adj;
  2175. lockZ1 = (z_endstop_adj > 0);
  2176. }
  2177. else
  2178. lockZ1 = (z_endstop_adj < 0);
  2179. if (lockZ1) stepper.set_z_lock(true); else stepper.set_z2_lock(true);
  2180. // Move to the adjusted endstop height
  2181. do_homing_move(axis, adj);
  2182. if (lockZ1) stepper.set_z_lock(false); else stepper.set_z2_lock(false);
  2183. stepper.set_homing_flag(false);
  2184. } // Z_AXIS
  2185. #endif
  2186. #if IS_SCARA
  2187. set_axis_is_at_home(axis);
  2188. SYNC_PLAN_POSITION_KINEMATIC();
  2189. #elif ENABLED(DELTA)
  2190. // Delta has already moved all three towers up in G28
  2191. // so here it re-homes each tower in turn.
  2192. // Delta homing treats the axes as normal linear axes.
  2193. // retrace by the amount specified in endstop_adj
  2194. if (endstop_adj[axis] * Z_HOME_DIR < 0) {
  2195. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2196. if (DEBUGGING(LEVELING)) {
  2197. SERIAL_ECHOPAIR("> endstop_adj = ", endstop_adj[axis] * Z_HOME_DIR);
  2198. DEBUG_POS("", current_position);
  2199. }
  2200. #endif
  2201. do_homing_move(axis, endstop_adj[axis]);
  2202. }
  2203. #else
  2204. // For cartesian/core machines,
  2205. // set the axis to its home position
  2206. set_axis_is_at_home(axis);
  2207. sync_plan_position();
  2208. destination[axis] = current_position[axis];
  2209. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2210. if (DEBUGGING(LEVELING)) DEBUG_POS("> AFTER set_axis_is_at_home", current_position);
  2211. #endif
  2212. #endif
  2213. // Put away the Z probe
  2214. #if HOMING_Z_WITH_PROBE
  2215. if (axis == Z_AXIS && STOW_PROBE()) return;
  2216. #endif
  2217. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2218. if (DEBUGGING(LEVELING)) {
  2219. SERIAL_ECHOPAIR("<<< homeaxis(", axis_codes[axis]);
  2220. SERIAL_ECHOLNPGM(")");
  2221. }
  2222. #endif
  2223. } // homeaxis()
  2224. #if ENABLED(FWRETRACT)
  2225. void retract(bool retracting, bool swapping = false) {
  2226. if (retracting == retracted[active_extruder]) return;
  2227. float old_feedrate_mm_s = feedrate_mm_s;
  2228. set_destination_to_current();
  2229. if (retracting) {
  2230. feedrate_mm_s = retract_feedrate_mm_s;
  2231. current_position[E_AXIS] += (swapping ? retract_length_swap : retract_length) / volumetric_multiplier[active_extruder];
  2232. sync_plan_position_e();
  2233. prepare_move_to_destination();
  2234. if (retract_zlift > 0.01) {
  2235. current_position[Z_AXIS] -= retract_zlift;
  2236. SYNC_PLAN_POSITION_KINEMATIC();
  2237. prepare_move_to_destination();
  2238. }
  2239. }
  2240. else {
  2241. if (retract_zlift > 0.01) {
  2242. current_position[Z_AXIS] += retract_zlift;
  2243. SYNC_PLAN_POSITION_KINEMATIC();
  2244. }
  2245. feedrate_mm_s = retract_recover_feedrate_mm_s;
  2246. float move_e = swapping ? retract_length_swap + retract_recover_length_swap : retract_length + retract_recover_length;
  2247. current_position[E_AXIS] -= move_e / volumetric_multiplier[active_extruder];
  2248. sync_plan_position_e();
  2249. prepare_move_to_destination();
  2250. }
  2251. feedrate_mm_s = old_feedrate_mm_s;
  2252. retracted[active_extruder] = retracting;
  2253. } // retract()
  2254. #endif // FWRETRACT
  2255. #if ENABLED(MIXING_EXTRUDER)
  2256. void normalize_mix() {
  2257. float mix_total = 0.0;
  2258. for (int i = 0; i < MIXING_STEPPERS; i++) {
  2259. float v = mixing_factor[i];
  2260. if (v < 0) v = mixing_factor[i] = 0;
  2261. mix_total += v;
  2262. }
  2263. // Scale all values if they don't add up to ~1.0
  2264. if (mix_total < 0.9999 || mix_total > 1.0001) {
  2265. SERIAL_PROTOCOLLNPGM("Warning: Mix factors must add up to 1.0. Scaling.");
  2266. float mix_scale = 1.0 / mix_total;
  2267. for (int i = 0; i < MIXING_STEPPERS; i++)
  2268. mixing_factor[i] *= mix_scale;
  2269. }
  2270. }
  2271. #if ENABLED(DIRECT_MIXING_IN_G1)
  2272. // Get mixing parameters from the GCode
  2273. // Factors that are left out are set to 0
  2274. // The total "must" be 1.0 (but it will be normalized)
  2275. void gcode_get_mix() {
  2276. const char* mixing_codes = "ABCDHI";
  2277. for (int i = 0; i < MIXING_STEPPERS; i++)
  2278. mixing_factor[i] = code_seen(mixing_codes[i]) ? code_value_float() : 0;
  2279. normalize_mix();
  2280. }
  2281. #endif
  2282. #endif
  2283. /**
  2284. * ***************************************************************************
  2285. * ***************************** G-CODE HANDLING *****************************
  2286. * ***************************************************************************
  2287. */
  2288. /**
  2289. * Set XYZE destination and feedrate from the current GCode command
  2290. *
  2291. * - Set destination from included axis codes
  2292. * - Set to current for missing axis codes
  2293. * - Set the feedrate, if included
  2294. */
  2295. void gcode_get_destination() {
  2296. LOOP_XYZE(i) {
  2297. if (code_seen(axis_codes[i]))
  2298. destination[i] = code_value_axis_units(i) + (axis_relative_modes[i] || relative_mode ? current_position[i] : 0);
  2299. else
  2300. destination[i] = current_position[i];
  2301. }
  2302. if (code_seen('F') && code_value_linear_units() > 0.0)
  2303. feedrate_mm_s = MMM_TO_MMS(code_value_linear_units());
  2304. #if ENABLED(PRINTCOUNTER)
  2305. if (!DEBUGGING(DRYRUN))
  2306. print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]);
  2307. #endif
  2308. // Get ABCDHI mixing factors
  2309. #if ENABLED(MIXING_EXTRUDER) && ENABLED(DIRECT_MIXING_IN_G1)
  2310. gcode_get_mix();
  2311. #endif
  2312. }
  2313. void unknown_command_error() {
  2314. SERIAL_ECHO_START;
  2315. SERIAL_ECHOPAIR(MSG_UNKNOWN_COMMAND, current_command);
  2316. SERIAL_ECHOLNPGM("\"");
  2317. }
  2318. #if ENABLED(HOST_KEEPALIVE_FEATURE)
  2319. /**
  2320. * Output a "busy" message at regular intervals
  2321. * while the machine is not accepting commands.
  2322. */
  2323. void host_keepalive() {
  2324. millis_t ms = millis();
  2325. if (host_keepalive_interval && busy_state != NOT_BUSY) {
  2326. if (PENDING(ms, next_busy_signal_ms)) return;
  2327. switch (busy_state) {
  2328. case IN_HANDLER:
  2329. case IN_PROCESS:
  2330. SERIAL_ECHO_START;
  2331. SERIAL_ECHOLNPGM(MSG_BUSY_PROCESSING);
  2332. break;
  2333. case PAUSED_FOR_USER:
  2334. SERIAL_ECHO_START;
  2335. SERIAL_ECHOLNPGM(MSG_BUSY_PAUSED_FOR_USER);
  2336. break;
  2337. case PAUSED_FOR_INPUT:
  2338. SERIAL_ECHO_START;
  2339. SERIAL_ECHOLNPGM(MSG_BUSY_PAUSED_FOR_INPUT);
  2340. break;
  2341. default:
  2342. break;
  2343. }
  2344. }
  2345. next_busy_signal_ms = ms + host_keepalive_interval * 1000UL;
  2346. }
  2347. #endif //HOST_KEEPALIVE_FEATURE
  2348. bool position_is_reachable(float target[XYZ]
  2349. #if HAS_BED_PROBE
  2350. , bool by_probe=false
  2351. #endif
  2352. ) {
  2353. float dx = RAW_X_POSITION(target[X_AXIS]),
  2354. dy = RAW_Y_POSITION(target[Y_AXIS]);
  2355. #if HAS_BED_PROBE
  2356. if (by_probe) {
  2357. dx -= X_PROBE_OFFSET_FROM_EXTRUDER;
  2358. dy -= Y_PROBE_OFFSET_FROM_EXTRUDER;
  2359. }
  2360. #endif
  2361. #if IS_SCARA
  2362. #if MIDDLE_DEAD_ZONE_R > 0
  2363. const float R2 = HYPOT2(dx - SCARA_OFFSET_X, dy - SCARA_OFFSET_Y);
  2364. return R2 >= sq(float(MIDDLE_DEAD_ZONE_R)) && R2 <= sq(L1 + L2);
  2365. #else
  2366. return HYPOT2(dx - SCARA_OFFSET_X, dy - SCARA_OFFSET_Y) <= sq(L1 + L2);
  2367. #endif
  2368. #elif ENABLED(DELTA)
  2369. return HYPOT2(dx, dy) <= sq(DELTA_PRINTABLE_RADIUS);
  2370. #else
  2371. const float dz = RAW_Z_POSITION(target[Z_AXIS]);
  2372. return dx >= X_MIN_POS - 0.0001 && dx <= X_MAX_POS + 0.0001
  2373. && dy >= Y_MIN_POS - 0.0001 && dy <= Y_MAX_POS + 0.0001
  2374. && dz >= Z_MIN_POS - 0.0001 && dz <= Z_MAX_POS + 0.0001;
  2375. #endif
  2376. }
  2377. /**************************************************
  2378. ***************** GCode Handlers *****************
  2379. **************************************************/
  2380. /**
  2381. * G0, G1: Coordinated movement of X Y Z E axes
  2382. */
  2383. inline void gcode_G0_G1(
  2384. #if IS_SCARA
  2385. bool fast_move=false
  2386. #endif
  2387. ) {
  2388. if (IsRunning()) {
  2389. gcode_get_destination(); // For X Y Z E F
  2390. #if ENABLED(FWRETRACT)
  2391. if (autoretract_enabled && !(code_seen('X') || code_seen('Y') || code_seen('Z')) && code_seen('E')) {
  2392. float echange = destination[E_AXIS] - current_position[E_AXIS];
  2393. // Is this move an attempt to retract or recover?
  2394. if ((echange < -MIN_RETRACT && !retracted[active_extruder]) || (echange > MIN_RETRACT && retracted[active_extruder])) {
  2395. current_position[E_AXIS] = destination[E_AXIS]; // hide the slicer-generated retract/recover from calculations
  2396. sync_plan_position_e(); // AND from the planner
  2397. retract(!retracted[active_extruder]);
  2398. return;
  2399. }
  2400. }
  2401. #endif //FWRETRACT
  2402. #if IS_SCARA
  2403. fast_move ? prepare_uninterpolated_move_to_destination() : prepare_move_to_destination();
  2404. #else
  2405. prepare_move_to_destination();
  2406. #endif
  2407. }
  2408. }
  2409. /**
  2410. * G2: Clockwise Arc
  2411. * G3: Counterclockwise Arc
  2412. *
  2413. * This command has two forms: IJ-form and R-form.
  2414. *
  2415. * - I specifies an X offset. J specifies a Y offset.
  2416. * At least one of the IJ parameters is required.
  2417. * X and Y can be omitted to do a complete circle.
  2418. * The given XY is not error-checked. The arc ends
  2419. * based on the angle of the destination.
  2420. * Mixing I or J with R will throw an error.
  2421. *
  2422. * - R specifies the radius. X or Y is required.
  2423. * Omitting both X and Y will throw an error.
  2424. * X or Y must differ from the current XY.
  2425. * Mixing R with I or J will throw an error.
  2426. *
  2427. * Examples:
  2428. *
  2429. * G2 I10 ; CW circle centered at X+10
  2430. * G3 X20 Y12 R14 ; CCW circle with r=14 ending at X20 Y12
  2431. */
  2432. #if ENABLED(ARC_SUPPORT)
  2433. inline void gcode_G2_G3(bool clockwise) {
  2434. if (IsRunning()) {
  2435. #if ENABLED(SF_ARC_FIX)
  2436. bool relative_mode_backup = relative_mode;
  2437. relative_mode = true;
  2438. #endif
  2439. gcode_get_destination();
  2440. #if ENABLED(SF_ARC_FIX)
  2441. relative_mode = relative_mode_backup;
  2442. #endif
  2443. float arc_offset[2] = { 0.0, 0.0 };
  2444. if (code_seen('R')) {
  2445. const float r = code_value_axis_units(X_AXIS),
  2446. x1 = current_position[X_AXIS], y1 = current_position[Y_AXIS],
  2447. x2 = destination[X_AXIS], y2 = destination[Y_AXIS];
  2448. if (r && (x2 != x1 || y2 != y1)) {
  2449. const float e = clockwise ? -1 : 1, // clockwise -1, counterclockwise 1
  2450. dx = x2 - x1, dy = y2 - y1, // X and Y differences
  2451. d = HYPOT(dx, dy), // Linear distance between the points
  2452. h = sqrt(sq(r) - sq(d * 0.5)), // Distance to the arc pivot-point
  2453. mx = (x1 + x2) * 0.5, my = (y1 + y2) * 0.5, // Point between the two points
  2454. sx = -dy / d, sy = dx / d, // Slope of the perpendicular bisector
  2455. cx = mx + e * h * sx, cy = my + e * h * sy; // Pivot-point of the arc
  2456. arc_offset[X_AXIS] = cx - x1;
  2457. arc_offset[Y_AXIS] = cy - y1;
  2458. }
  2459. }
  2460. else {
  2461. if (code_seen('I')) arc_offset[X_AXIS] = code_value_axis_units(X_AXIS);
  2462. if (code_seen('J')) arc_offset[Y_AXIS] = code_value_axis_units(Y_AXIS);
  2463. }
  2464. if (arc_offset[0] || arc_offset[1]) {
  2465. // Send an arc to the planner
  2466. plan_arc(destination, arc_offset, clockwise);
  2467. refresh_cmd_timeout();
  2468. }
  2469. else {
  2470. // Bad arguments
  2471. SERIAL_ERROR_START;
  2472. SERIAL_ERRORLNPGM(MSG_ERR_ARC_ARGS);
  2473. }
  2474. }
  2475. }
  2476. #endif
  2477. /**
  2478. * G4: Dwell S<seconds> or P<milliseconds>
  2479. */
  2480. inline void gcode_G4() {
  2481. millis_t dwell_ms = 0;
  2482. if (code_seen('P')) dwell_ms = code_value_millis(); // milliseconds to wait
  2483. if (code_seen('S')) dwell_ms = code_value_millis_from_seconds(); // seconds to wait
  2484. stepper.synchronize();
  2485. refresh_cmd_timeout();
  2486. dwell_ms += previous_cmd_ms; // keep track of when we started waiting
  2487. if (!lcd_hasstatus()) LCD_MESSAGEPGM(MSG_DWELL);
  2488. while (PENDING(millis(), dwell_ms)) idle();
  2489. }
  2490. #if ENABLED(BEZIER_CURVE_SUPPORT)
  2491. /**
  2492. * Parameters interpreted according to:
  2493. * http://linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G5-Cubic-Spline
  2494. * However I, J omission is not supported at this point; all
  2495. * parameters can be omitted and default to zero.
  2496. */
  2497. /**
  2498. * G5: Cubic B-spline
  2499. */
  2500. inline void gcode_G5() {
  2501. if (IsRunning()) {
  2502. gcode_get_destination();
  2503. float offset[] = {
  2504. code_seen('I') ? code_value_axis_units(X_AXIS) : 0.0,
  2505. code_seen('J') ? code_value_axis_units(Y_AXIS) : 0.0,
  2506. code_seen('P') ? code_value_axis_units(X_AXIS) : 0.0,
  2507. code_seen('Q') ? code_value_axis_units(Y_AXIS) : 0.0
  2508. };
  2509. plan_cubic_move(offset);
  2510. }
  2511. }
  2512. #endif // BEZIER_CURVE_SUPPORT
  2513. #if ENABLED(FWRETRACT)
  2514. /**
  2515. * G10 - Retract filament according to settings of M207
  2516. * G11 - Recover filament according to settings of M208
  2517. */
  2518. inline void gcode_G10_G11(bool doRetract=false) {
  2519. #if EXTRUDERS > 1
  2520. if (doRetract) {
  2521. retracted_swap[active_extruder] = (code_seen('S') && code_value_bool()); // checks for swap retract argument
  2522. }
  2523. #endif
  2524. retract(doRetract
  2525. #if EXTRUDERS > 1
  2526. , retracted_swap[active_extruder]
  2527. #endif
  2528. );
  2529. }
  2530. #endif //FWRETRACT
  2531. #if ENABLED(NOZZLE_CLEAN_FEATURE)
  2532. /**
  2533. * G12: Clean the nozzle
  2534. */
  2535. inline void gcode_G12() {
  2536. // Don't allow nozzle cleaning without homing first
  2537. if (axis_unhomed_error(true, true, true)) { return; }
  2538. uint8_t const pattern = code_seen('P') ? code_value_ushort() : 0;
  2539. uint8_t const strokes = code_seen('S') ? code_value_ushort() : NOZZLE_CLEAN_STROKES;
  2540. uint8_t const objects = code_seen('T') ? code_value_ushort() : 3;
  2541. Nozzle::clean(pattern, strokes, objects);
  2542. }
  2543. #endif
  2544. #if ENABLED(INCH_MODE_SUPPORT)
  2545. /**
  2546. * G20: Set input mode to inches
  2547. */
  2548. inline void gcode_G20() { set_input_linear_units(LINEARUNIT_INCH); }
  2549. /**
  2550. * G21: Set input mode to millimeters
  2551. */
  2552. inline void gcode_G21() { set_input_linear_units(LINEARUNIT_MM); }
  2553. #endif
  2554. #if ENABLED(NOZZLE_PARK_FEATURE)
  2555. /**
  2556. * G27: Park the nozzle
  2557. */
  2558. inline void gcode_G27() {
  2559. // Don't allow nozzle parking without homing first
  2560. if (axis_unhomed_error(true, true, true)) { return; }
  2561. uint8_t const z_action = code_seen('P') ? code_value_ushort() : 0;
  2562. Nozzle::park(z_action);
  2563. }
  2564. #endif // NOZZLE_PARK_FEATURE
  2565. #if ENABLED(QUICK_HOME)
  2566. static void quick_home_xy() {
  2567. // Pretend the current position is 0,0
  2568. current_position[X_AXIS] = current_position[Y_AXIS] = 0.0;
  2569. sync_plan_position();
  2570. int x_axis_home_dir =
  2571. #if ENABLED(DUAL_X_CARRIAGE)
  2572. x_home_dir(active_extruder)
  2573. #else
  2574. home_dir(X_AXIS)
  2575. #endif
  2576. ;
  2577. float mlx = max_length(X_AXIS),
  2578. mly = max_length(Y_AXIS),
  2579. mlratio = mlx > mly ? mly / mlx : mlx / mly,
  2580. fr_mm_s = min(homing_feedrate_mm_s[X_AXIS], homing_feedrate_mm_s[Y_AXIS]) * sqrt(sq(mlratio) + 1.0);
  2581. do_blocking_move_to_xy(1.5 * mlx * x_axis_home_dir, 1.5 * mly * home_dir(Y_AXIS), fr_mm_s);
  2582. endstops.hit_on_purpose(); // clear endstop hit flags
  2583. current_position[X_AXIS] = current_position[Y_AXIS] = 0.0;
  2584. }
  2585. #endif // QUICK_HOME
  2586. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2587. void log_machine_info() {
  2588. SERIAL_ECHOPGM("Machine Type: ");
  2589. #if ENABLED(DELTA)
  2590. SERIAL_ECHOLNPGM("Delta");
  2591. #elif IS_SCARA
  2592. SERIAL_ECHOLNPGM("SCARA");
  2593. #elif ENABLED(COREXY) || ENABLED(COREXZ) || ENABLED(COREYZ)
  2594. SERIAL_ECHOLNPGM("Core");
  2595. #else
  2596. SERIAL_ECHOLNPGM("Cartesian");
  2597. #endif
  2598. SERIAL_ECHOPGM("Probe: ");
  2599. #if ENABLED(FIX_MOUNTED_PROBE)
  2600. SERIAL_ECHOLNPGM("FIX_MOUNTED_PROBE");
  2601. #elif ENABLED(BLTOUCH)
  2602. SERIAL_ECHOLNPGM("BLTOUCH");
  2603. #elif HAS_Z_SERVO_ENDSTOP
  2604. SERIAL_ECHOLNPGM("SERVO PROBE");
  2605. #elif ENABLED(Z_PROBE_SLED)
  2606. SERIAL_ECHOLNPGM("Z_PROBE_SLED");
  2607. #elif ENABLED(Z_PROBE_ALLEN_KEY)
  2608. SERIAL_ECHOLNPGM("Z_PROBE_ALLEN_KEY");
  2609. #else
  2610. SERIAL_ECHOLNPGM("NONE");
  2611. #endif
  2612. #if HAS_BED_PROBE
  2613. SERIAL_ECHOPAIR("Probe Offset X:", X_PROBE_OFFSET_FROM_EXTRUDER);
  2614. SERIAL_ECHOPAIR(" Y:", Y_PROBE_OFFSET_FROM_EXTRUDER);
  2615. SERIAL_ECHOPAIR(" Z:", zprobe_zoffset);
  2616. #if (X_PROBE_OFFSET_FROM_EXTRUDER > 0)
  2617. SERIAL_ECHOPGM(" (Right");
  2618. #elif (X_PROBE_OFFSET_FROM_EXTRUDER < 0)
  2619. SERIAL_ECHOPGM(" (Left");
  2620. #elif (Y_PROBE_OFFSET_FROM_EXTRUDER != 0)
  2621. SERIAL_ECHOPGM(" (Middle");
  2622. #else
  2623. SERIAL_ECHOPGM(" (Aligned With");
  2624. #endif
  2625. #if (Y_PROBE_OFFSET_FROM_EXTRUDER > 0)
  2626. SERIAL_ECHOPGM("-Back");
  2627. #elif (Y_PROBE_OFFSET_FROM_EXTRUDER < 0)
  2628. SERIAL_ECHOPGM("-Front");
  2629. #elif (X_PROBE_OFFSET_FROM_EXTRUDER != 0)
  2630. SERIAL_ECHOPGM("-Center");
  2631. #endif
  2632. if (zprobe_zoffset < 0)
  2633. SERIAL_ECHOPGM(" & Below");
  2634. else if (zprobe_zoffset > 0)
  2635. SERIAL_ECHOPGM(" & Above");
  2636. else
  2637. SERIAL_ECHOPGM(" & Same Z as");
  2638. SERIAL_ECHOLNPGM(" Nozzle)");
  2639. #endif
  2640. #if HAS_ABL
  2641. SERIAL_ECHOPGM("Auto Bed Leveling: ");
  2642. #if ENABLED(AUTO_BED_LEVELING_LINEAR)
  2643. SERIAL_ECHOPGM("LINEAR");
  2644. #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
  2645. SERIAL_ECHOPGM("BILINEAR");
  2646. #elif ENABLED(AUTO_BED_LEVELING_3POINT)
  2647. SERIAL_ECHOPGM("3POINT");
  2648. #endif
  2649. if (planner.abl_enabled) {
  2650. SERIAL_ECHOLNPGM(" (enabled)");
  2651. #if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_3POINT)
  2652. float diff[XYZ] = {
  2653. stepper.get_axis_position_mm(X_AXIS) - current_position[X_AXIS],
  2654. stepper.get_axis_position_mm(Y_AXIS) - current_position[Y_AXIS],
  2655. stepper.get_axis_position_mm(Z_AXIS) - current_position[Z_AXIS]
  2656. };
  2657. SERIAL_ECHOPGM("ABL Adjustment X");
  2658. if (diff[X_AXIS] > 0) SERIAL_CHAR('+');
  2659. SERIAL_ECHO(diff[X_AXIS]);
  2660. SERIAL_ECHOPGM(" Y");
  2661. if (diff[Y_AXIS] > 0) SERIAL_CHAR('+');
  2662. SERIAL_ECHO(diff[Y_AXIS]);
  2663. SERIAL_ECHOPGM(" Z");
  2664. if (diff[Z_AXIS] > 0) SERIAL_CHAR('+');
  2665. SERIAL_ECHO(diff[Z_AXIS]);
  2666. #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
  2667. SERIAL_ECHOPAIR("ABL Adjustment Z", bilinear_z_offset(current_position));
  2668. #endif
  2669. }
  2670. SERIAL_EOL;
  2671. #elif ENABLED(MESH_BED_LEVELING)
  2672. SERIAL_ECHOPGM("Mesh Bed Leveling");
  2673. if (mbl.active()) {
  2674. SERIAL_ECHOLNPGM(" (enabled)");
  2675. SERIAL_ECHOPAIR("MBL Adjustment Z", mbl.get_z(RAW_CURRENT_POSITION(X_AXIS), RAW_CURRENT_POSITION(Y_AXIS)));
  2676. }
  2677. SERIAL_EOL;
  2678. #endif
  2679. }
  2680. #endif // DEBUG_LEVELING_FEATURE
  2681. #if ENABLED(DELTA)
  2682. /**
  2683. * A delta can only safely home all axes at the same time
  2684. * This is like quick_home_xy() but for 3 towers.
  2685. */
  2686. inline void home_delta() {
  2687. // Init the current position of all carriages to 0,0,0
  2688. memset(current_position, 0, sizeof(current_position));
  2689. sync_plan_position();
  2690. // Move all carriages together linearly until an endstop is hit.
  2691. current_position[X_AXIS] = current_position[Y_AXIS] = current_position[Z_AXIS] = (Z_MAX_LENGTH + 10);
  2692. feedrate_mm_s = homing_feedrate_mm_s[X_AXIS];
  2693. line_to_current_position();
  2694. stepper.synchronize();
  2695. endstops.hit_on_purpose(); // clear endstop hit flags
  2696. // Probably not needed. Double-check this line:
  2697. memset(current_position, 0, sizeof(current_position));
  2698. // At least one carriage has reached the top.
  2699. // Now back off and re-home each carriage separately.
  2700. HOMEAXIS(A);
  2701. HOMEAXIS(B);
  2702. HOMEAXIS(C);
  2703. // Set all carriages to their home positions
  2704. // Do this here all at once for Delta, because
  2705. // XYZ isn't ABC. Applying this per-tower would
  2706. // give the impression that they are the same.
  2707. LOOP_XYZ(i) set_axis_is_at_home((AxisEnum)i);
  2708. SYNC_PLAN_POSITION_KINEMATIC();
  2709. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2710. if (DEBUGGING(LEVELING)) DEBUG_POS("(DELTA)", current_position);
  2711. #endif
  2712. }
  2713. #endif // DELTA
  2714. #if ENABLED(Z_SAFE_HOMING)
  2715. inline void home_z_safely() {
  2716. // Disallow Z homing if X or Y are unknown
  2717. if (!axis_known_position[X_AXIS] || !axis_known_position[Y_AXIS]) {
  2718. LCD_MESSAGEPGM(MSG_ERR_Z_HOMING);
  2719. SERIAL_ECHO_START;
  2720. SERIAL_ECHOLNPGM(MSG_ERR_Z_HOMING);
  2721. return;
  2722. }
  2723. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2724. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("Z_SAFE_HOMING >>>");
  2725. #endif
  2726. SYNC_PLAN_POSITION_KINEMATIC();
  2727. /**
  2728. * Move the Z probe (or just the nozzle) to the safe homing point
  2729. */
  2730. destination[X_AXIS] = LOGICAL_X_POSITION(Z_SAFE_HOMING_X_POINT);
  2731. destination[Y_AXIS] = LOGICAL_Y_POSITION(Z_SAFE_HOMING_Y_POINT);
  2732. destination[Z_AXIS] = current_position[Z_AXIS]; // Z is already at the right height
  2733. if (position_is_reachable(
  2734. destination
  2735. #if HOMING_Z_WITH_PROBE
  2736. , true
  2737. #endif
  2738. )
  2739. ) {
  2740. #if HOMING_Z_WITH_PROBE
  2741. destination[X_AXIS] -= X_PROBE_OFFSET_FROM_EXTRUDER;
  2742. destination[Y_AXIS] -= Y_PROBE_OFFSET_FROM_EXTRUDER;
  2743. #endif
  2744. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2745. if (DEBUGGING(LEVELING)) DEBUG_POS("Z_SAFE_HOMING", destination);
  2746. #endif
  2747. do_blocking_move_to_xy(destination[X_AXIS], destination[Y_AXIS]);
  2748. HOMEAXIS(Z);
  2749. }
  2750. else {
  2751. LCD_MESSAGEPGM(MSG_ZPROBE_OUT);
  2752. SERIAL_ECHO_START;
  2753. SERIAL_ECHOLNPGM(MSG_ZPROBE_OUT);
  2754. }
  2755. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2756. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< Z_SAFE_HOMING");
  2757. #endif
  2758. }
  2759. #endif // Z_SAFE_HOMING
  2760. /**
  2761. * G28: Home all axes according to settings
  2762. *
  2763. * Parameters
  2764. *
  2765. * None Home to all axes with no parameters.
  2766. * With QUICK_HOME enabled XY will home together, then Z.
  2767. *
  2768. * Cartesian parameters
  2769. *
  2770. * X Home to the X endstop
  2771. * Y Home to the Y endstop
  2772. * Z Home to the Z endstop
  2773. *
  2774. */
  2775. inline void gcode_G28() {
  2776. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2777. if (DEBUGGING(LEVELING)) {
  2778. SERIAL_ECHOLNPGM(">>> gcode_G28");
  2779. log_machine_info();
  2780. }
  2781. #endif
  2782. // Wait for planner moves to finish!
  2783. stepper.synchronize();
  2784. // For auto bed leveling, clear the level matrix
  2785. #if HAS_ABL
  2786. reset_bed_level();
  2787. #endif
  2788. // Always home with tool 0 active
  2789. #if HOTENDS > 1
  2790. uint8_t old_tool_index = active_extruder;
  2791. tool_change(0, 0, true);
  2792. #endif
  2793. #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
  2794. extruder_duplication_enabled = false;
  2795. #endif
  2796. /**
  2797. * For mesh bed leveling deactivate the mesh calculations, will be turned
  2798. * on again when homing all axis
  2799. */
  2800. #if ENABLED(MESH_BED_LEVELING)
  2801. float pre_home_z = MESH_HOME_SEARCH_Z;
  2802. if (mbl.active()) {
  2803. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2804. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("MBL was active");
  2805. #endif
  2806. // Save known Z position if already homed
  2807. if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) {
  2808. pre_home_z = current_position[Z_AXIS];
  2809. pre_home_z += mbl.get_z(RAW_CURRENT_POSITION(X_AXIS), RAW_CURRENT_POSITION(Y_AXIS));
  2810. }
  2811. mbl.set_active(false);
  2812. current_position[Z_AXIS] = pre_home_z;
  2813. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2814. if (DEBUGGING(LEVELING)) DEBUG_POS("Set Z to pre_home_z", current_position);
  2815. #endif
  2816. }
  2817. #endif
  2818. setup_for_endstop_or_probe_move();
  2819. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2820. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> endstops.enable(true)");
  2821. #endif
  2822. endstops.enable(true); // Enable endstops for next homing move
  2823. #if ENABLED(DELTA)
  2824. home_delta();
  2825. #else // NOT DELTA
  2826. bool homeX = code_seen('X'), homeY = code_seen('Y'), homeZ = code_seen('Z');
  2827. home_all_axis = (!homeX && !homeY && !homeZ) || (homeX && homeY && homeZ);
  2828. set_destination_to_current();
  2829. #if Z_HOME_DIR > 0 // If homing away from BED do Z first
  2830. if (home_all_axis || homeZ) {
  2831. HOMEAXIS(Z);
  2832. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2833. if (DEBUGGING(LEVELING)) DEBUG_POS("> HOMEAXIS(Z)", current_position);
  2834. #endif
  2835. }
  2836. #else
  2837. if (home_all_axis || homeX || homeY) {
  2838. // Raise Z before homing any other axes and z is not already high enough (never lower z)
  2839. destination[Z_AXIS] = LOGICAL_Z_POSITION(Z_HOMING_HEIGHT);
  2840. if (destination[Z_AXIS] > current_position[Z_AXIS]) {
  2841. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2842. if (DEBUGGING(LEVELING))
  2843. SERIAL_ECHOLNPAIR("Raise Z (before homing) to ", destination[Z_AXIS]);
  2844. #endif
  2845. do_blocking_move_to_z(destination[Z_AXIS]);
  2846. }
  2847. }
  2848. #endif
  2849. #if ENABLED(QUICK_HOME)
  2850. if (home_all_axis || (homeX && homeY)) quick_home_xy();
  2851. #endif
  2852. #if ENABLED(HOME_Y_BEFORE_X)
  2853. // Home Y
  2854. if (home_all_axis || homeY) {
  2855. HOMEAXIS(Y);
  2856. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2857. if (DEBUGGING(LEVELING)) DEBUG_POS("> homeY", current_position);
  2858. #endif
  2859. }
  2860. #endif
  2861. // Home X
  2862. if (home_all_axis || homeX) {
  2863. #if ENABLED(DUAL_X_CARRIAGE)
  2864. int tmp_extruder = active_extruder;
  2865. active_extruder = !active_extruder;
  2866. HOMEAXIS(X);
  2867. inactive_extruder_x_pos = RAW_X_POSITION(current_position[X_AXIS]);
  2868. active_extruder = tmp_extruder;
  2869. HOMEAXIS(X);
  2870. // reset state used by the different modes
  2871. memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
  2872. delayed_move_time = 0;
  2873. active_extruder_parked = true;
  2874. #else
  2875. HOMEAXIS(X);
  2876. #endif
  2877. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2878. if (DEBUGGING(LEVELING)) DEBUG_POS("> homeX", current_position);
  2879. #endif
  2880. }
  2881. #if DISABLED(HOME_Y_BEFORE_X)
  2882. // Home Y
  2883. if (home_all_axis || homeY) {
  2884. HOMEAXIS(Y);
  2885. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2886. if (DEBUGGING(LEVELING)) DEBUG_POS("> homeY", current_position);
  2887. #endif
  2888. }
  2889. #endif
  2890. // Home Z last if homing towards the bed
  2891. #if Z_HOME_DIR < 0
  2892. if (home_all_axis || homeZ) {
  2893. #if ENABLED(Z_SAFE_HOMING)
  2894. home_z_safely();
  2895. #else
  2896. HOMEAXIS(Z);
  2897. #endif
  2898. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2899. if (DEBUGGING(LEVELING)) DEBUG_POS("> (home_all_axis || homeZ) > final", current_position);
  2900. #endif
  2901. } // home_all_axis || homeZ
  2902. #endif // Z_HOME_DIR < 0
  2903. SYNC_PLAN_POSITION_KINEMATIC();
  2904. #endif // !DELTA (gcode_G28)
  2905. endstops.not_homing();
  2906. // Enable mesh leveling again
  2907. #if ENABLED(MESH_BED_LEVELING)
  2908. if (mbl.has_mesh()) {
  2909. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2910. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("MBL has mesh");
  2911. #endif
  2912. if (home_all_axis || (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && homeZ)) {
  2913. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2914. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("MBL Z homing");
  2915. #endif
  2916. current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
  2917. #if Z_HOME_DIR > 0
  2918. + Z_MAX_POS
  2919. #endif
  2920. ;
  2921. SYNC_PLAN_POSITION_KINEMATIC();
  2922. mbl.set_active(true);
  2923. #if ENABLED(MESH_G28_REST_ORIGIN)
  2924. current_position[Z_AXIS] = 0.0;
  2925. set_destination_to_current();
  2926. line_to_destination(homing_feedrate_mm_s[Z_AXIS]);
  2927. stepper.synchronize();
  2928. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2929. if (DEBUGGING(LEVELING)) DEBUG_POS("MBL Rest Origin", current_position);
  2930. #endif
  2931. #else
  2932. planner.unapply_leveling(current_position);
  2933. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2934. if (DEBUGGING(LEVELING)) DEBUG_POS("MBL adjusted MESH_HOME_SEARCH_Z", current_position);
  2935. #endif
  2936. #endif
  2937. }
  2938. else if ((axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) && (homeX || homeY)) {
  2939. current_position[Z_AXIS] = pre_home_z;
  2940. SYNC_PLAN_POSITION_KINEMATIC();
  2941. mbl.set_active(true);
  2942. planner.unapply_leveling(current_position);
  2943. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2944. if (DEBUGGING(LEVELING)) DEBUG_POS("MBL Home X or Y", current_position);
  2945. #endif
  2946. }
  2947. }
  2948. #endif
  2949. #if ENABLED(DELTA)
  2950. // move to a height where we can use the full xy-area
  2951. do_blocking_move_to_z(delta_clip_start_height);
  2952. #endif
  2953. clean_up_after_endstop_or_probe_move();
  2954. #if ENABLED(DEBUG_LEVELING_FEATURE)
  2955. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< gcode_G28");
  2956. #endif
  2957. // Restore the active tool after homing
  2958. #if HOTENDS > 1
  2959. tool_change(old_tool_index, 0, true);
  2960. #endif
  2961. report_current_position();
  2962. }
  2963. #if HAS_PROBING_PROCEDURE
  2964. void out_of_range_error(const char* p_edge) {
  2965. SERIAL_PROTOCOLPGM("?Probe ");
  2966. serialprintPGM(p_edge);
  2967. SERIAL_PROTOCOLLNPGM(" position out of range.");
  2968. }
  2969. #endif
  2970. #if ENABLED(MESH_BED_LEVELING)
  2971. inline void _mbl_goto_xy(float x, float y) {
  2972. float old_feedrate_mm_s = feedrate_mm_s;
  2973. feedrate_mm_s = homing_feedrate_mm_s[X_AXIS];
  2974. current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
  2975. #if Z_CLEARANCE_BETWEEN_PROBES > Z_HOMING_HEIGHT
  2976. + Z_CLEARANCE_BETWEEN_PROBES
  2977. #elif Z_HOMING_HEIGHT > 0
  2978. + Z_HOMING_HEIGHT
  2979. #endif
  2980. ;
  2981. line_to_current_position();
  2982. current_position[X_AXIS] = LOGICAL_X_POSITION(x);
  2983. current_position[Y_AXIS] = LOGICAL_Y_POSITION(y);
  2984. line_to_current_position();
  2985. #if Z_CLEARANCE_BETWEEN_PROBES > 0 || Z_HOMING_HEIGHT > 0
  2986. current_position[Z_AXIS] = LOGICAL_Z_POSITION(MESH_HOME_SEARCH_Z);
  2987. line_to_current_position();
  2988. #endif
  2989. feedrate_mm_s = old_feedrate_mm_s;
  2990. stepper.synchronize();
  2991. }
  2992. /**
  2993. * G29: Mesh-based Z probe, probes a grid and produces a
  2994. * mesh to compensate for variable bed height
  2995. *
  2996. * Parameters With MESH_BED_LEVELING:
  2997. *
  2998. * S0 Produce a mesh report
  2999. * S1 Start probing mesh points
  3000. * S2 Probe the next mesh point
  3001. * S3 Xn Yn Zn.nn Manually modify a single point
  3002. * S4 Zn.nn Set z offset. Positive away from bed, negative closer to bed.
  3003. * S5 Reset and disable mesh
  3004. *
  3005. * The S0 report the points as below
  3006. *
  3007. * +----> X-axis 1-n
  3008. * |
  3009. * |
  3010. * v Y-axis 1-n
  3011. *
  3012. */
  3013. inline void gcode_G29() {
  3014. static int probe_point = -1;
  3015. MeshLevelingState state = code_seen('S') ? (MeshLevelingState)code_value_byte() : MeshReport;
  3016. if (state < 0 || state > 5) {
  3017. SERIAL_PROTOCOLLNPGM("S out of range (0-5).");
  3018. return;
  3019. }
  3020. int8_t px, py;
  3021. switch (state) {
  3022. case MeshReport:
  3023. if (mbl.has_mesh()) {
  3024. SERIAL_PROTOCOLPAIR("State: ", mbl.active() ? MSG_ON : MSG_OFF);
  3025. SERIAL_PROTOCOLLNPGM("\nNum X,Y: " STRINGIFY(MESH_NUM_X_POINTS) "," STRINGIFY(MESH_NUM_Y_POINTS));
  3026. SERIAL_PROTOCOLLNPGM("Z search height: " STRINGIFY(MESH_HOME_SEARCH_Z));
  3027. SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5);
  3028. SERIAL_PROTOCOLLNPGM("\nMeasured points:");
  3029. for (py = 0; py < MESH_NUM_Y_POINTS; py++) {
  3030. for (px = 0; px < MESH_NUM_X_POINTS; px++) {
  3031. SERIAL_PROTOCOLPGM(" ");
  3032. SERIAL_PROTOCOL_F(mbl.z_values[py][px], 5);
  3033. }
  3034. SERIAL_EOL;
  3035. }
  3036. }
  3037. else
  3038. SERIAL_PROTOCOLLNPGM("Mesh bed leveling not active.");
  3039. break;
  3040. case MeshStart:
  3041. mbl.reset();
  3042. probe_point = 0;
  3043. enqueue_and_echo_commands_P(PSTR("G28\nG29 S2"));
  3044. break;
  3045. case MeshNext:
  3046. if (probe_point < 0) {
  3047. SERIAL_PROTOCOLLNPGM("Start mesh probing with \"G29 S1\" first.");
  3048. return;
  3049. }
  3050. // For each G29 S2...
  3051. if (probe_point == 0) {
  3052. // For the initial G29 S2 make Z a positive value (e.g., 4.0)
  3053. current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
  3054. #if Z_HOME_DIR > 0
  3055. + Z_MAX_POS
  3056. #endif
  3057. ;
  3058. SYNC_PLAN_POSITION_KINEMATIC();
  3059. }
  3060. else {
  3061. // For G29 S2 after adjusting Z.
  3062. mbl.set_zigzag_z(probe_point - 1, current_position[Z_AXIS]);
  3063. }
  3064. // If there's another point to sample, move there with optional lift.
  3065. if (probe_point < (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
  3066. mbl.zigzag(probe_point, px, py);
  3067. _mbl_goto_xy(mbl.get_probe_x(px), mbl.get_probe_y(py));
  3068. probe_point++;
  3069. }
  3070. else {
  3071. // One last "return to the bed" (as originally coded) at completion
  3072. current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
  3073. #if Z_CLEARANCE_BETWEEN_PROBES > Z_HOMING_HEIGHT
  3074. + Z_CLEARANCE_BETWEEN_PROBES
  3075. #elif Z_HOMING_HEIGHT > 0
  3076. + Z_HOMING_HEIGHT
  3077. #endif
  3078. ;
  3079. line_to_current_position();
  3080. stepper.synchronize();
  3081. // After recording the last point, activate the mbl and home
  3082. SERIAL_PROTOCOLLNPGM("Mesh probing done.");
  3083. probe_point = -1;
  3084. mbl.set_has_mesh(true);
  3085. enqueue_and_echo_commands_P(PSTR("G28"));
  3086. }
  3087. break;
  3088. case MeshSet:
  3089. if (code_seen('X')) {
  3090. px = code_value_int() - 1;
  3091. if (px < 0 || px >= MESH_NUM_X_POINTS) {
  3092. SERIAL_PROTOCOLLNPGM("X out of range (1-" STRINGIFY(MESH_NUM_X_POINTS) ").");
  3093. return;
  3094. }
  3095. }
  3096. else {
  3097. SERIAL_PROTOCOLLNPGM("X not entered.");
  3098. return;
  3099. }
  3100. if (code_seen('Y')) {
  3101. py = code_value_int() - 1;
  3102. if (py < 0 || py >= MESH_NUM_Y_POINTS) {
  3103. SERIAL_PROTOCOLLNPGM("Y out of range (1-" STRINGIFY(MESH_NUM_Y_POINTS) ").");
  3104. return;
  3105. }
  3106. }
  3107. else {
  3108. SERIAL_PROTOCOLLNPGM("Y not entered.");
  3109. return;
  3110. }
  3111. if (code_seen('Z')) {
  3112. mbl.z_values[py][px] = code_value_axis_units(Z_AXIS);
  3113. }
  3114. else {
  3115. SERIAL_PROTOCOLLNPGM("Z not entered.");
  3116. return;
  3117. }
  3118. break;
  3119. case MeshSetZOffset:
  3120. if (code_seen('Z')) {
  3121. mbl.z_offset = code_value_axis_units(Z_AXIS);
  3122. }
  3123. else {
  3124. SERIAL_PROTOCOLLNPGM("Z not entered.");
  3125. return;
  3126. }
  3127. break;
  3128. case MeshReset:
  3129. if (mbl.active()) {
  3130. current_position[Z_AXIS] +=
  3131. mbl.get_z(RAW_CURRENT_POSITION(X_AXIS), RAW_CURRENT_POSITION(Y_AXIS)) - MESH_HOME_SEARCH_Z;
  3132. mbl.reset();
  3133. SYNC_PLAN_POSITION_KINEMATIC();
  3134. }
  3135. else
  3136. mbl.reset();
  3137. } // switch(state)
  3138. report_current_position();
  3139. }
  3140. #elif HAS_ABL
  3141. /**
  3142. * G29: Detailed Z probe, probes the bed at 3 or more points.
  3143. * Will fail if the printer has not been homed with G28.
  3144. *
  3145. * Enhanced G29 Auto Bed Leveling Probe Routine
  3146. *
  3147. * Parameters With ABL_GRID:
  3148. *
  3149. * P Set the size of the grid that will be probed (P x P points).
  3150. * Not supported by non-linear delta printer bed leveling.
  3151. * Example: "G29 P4"
  3152. *
  3153. * S Set the XY travel speed between probe points (in units/min)
  3154. *
  3155. * D Dry-Run mode. Just evaluate the bed Topology - Don't apply
  3156. * or clean the rotation Matrix. Useful to check the topology
  3157. * after a first run of G29.
  3158. *
  3159. * V Set the verbose level (0-4). Example: "G29 V3"
  3160. *
  3161. * T Generate a Bed Topology Report. Example: "G29 P5 T" for a detailed report.
  3162. * This is useful for manual bed leveling and finding flaws in the bed (to
  3163. * assist with part placement).
  3164. * Not supported by non-linear delta printer bed leveling.
  3165. *
  3166. * F Set the Front limit of the probing grid
  3167. * B Set the Back limit of the probing grid
  3168. * L Set the Left limit of the probing grid
  3169. * R Set the Right limit of the probing grid
  3170. *
  3171. * Global Parameters:
  3172. *
  3173. * E/e By default G29 will engage the Z probe, test the bed, then disengage.
  3174. * Include "E" to engage/disengage the Z probe for each sample.
  3175. * There's no extra effect if you have a fixed Z probe.
  3176. * Usage: "G29 E" or "G29 e"
  3177. *
  3178. */
  3179. inline void gcode_G29() {
  3180. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3181. bool query = code_seen('Q');
  3182. uint8_t old_debug_flags = marlin_debug_flags;
  3183. if (query) marlin_debug_flags |= DEBUG_LEVELING;
  3184. if (DEBUGGING(LEVELING)) {
  3185. DEBUG_POS(">>> gcode_G29", current_position);
  3186. log_machine_info();
  3187. }
  3188. marlin_debug_flags = old_debug_flags;
  3189. if (query) return;
  3190. #endif
  3191. // Don't allow auto-leveling without homing first
  3192. if (axis_unhomed_error(true, true, true)) return;
  3193. int verbose_level = code_seen('V') ? code_value_int() : 1;
  3194. if (verbose_level < 0 || verbose_level > 4) {
  3195. SERIAL_PROTOCOLLNPGM("?(V)erbose Level is implausible (0-4).");
  3196. return;
  3197. }
  3198. bool dryrun = code_seen('D'),
  3199. stow_probe_after_each = code_seen('E');
  3200. #if ABL_GRID
  3201. if (verbose_level > 0) {
  3202. SERIAL_PROTOCOLLNPGM("G29 Auto Bed Leveling");
  3203. if (dryrun) SERIAL_PROTOCOLLNPGM("Running in DRY-RUN mode");
  3204. }
  3205. #if ABL_PLANAR
  3206. bool do_topography_map = verbose_level > 2 || code_seen('T');
  3207. // X and Y specify points in each direction, overriding the default
  3208. // These values may be saved with the completed mesh
  3209. int abl_grid_points_x = code_seen('X') ? code_value_int() : ABL_GRID_POINTS_X,
  3210. abl_grid_points_y = code_seen('Y') ? code_value_int() : ABL_GRID_POINTS_Y;
  3211. if (code_seen('P')) abl_grid_points_x = abl_grid_points_y = code_value_int();
  3212. if (abl_grid_points_x < 2 || abl_grid_points_y < 2) {
  3213. SERIAL_PROTOCOLLNPGM("?Number of probe points is implausible (2 minimum).");
  3214. return;
  3215. }
  3216. #else
  3217. const int abl_grid_points_x = ABL_GRID_POINTS_X, abl_grid_points_y = ABL_GRID_POINTS_Y;
  3218. #endif
  3219. xy_probe_feedrate_mm_s = MMM_TO_MMS(code_seen('S') ? code_value_linear_units() : XY_PROBE_SPEED);
  3220. int left_probe_bed_position = code_seen('L') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(LEFT_PROBE_BED_POSITION),
  3221. right_probe_bed_position = code_seen('R') ? (int)code_value_axis_units(X_AXIS) : LOGICAL_X_POSITION(RIGHT_PROBE_BED_POSITION),
  3222. front_probe_bed_position = code_seen('F') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(FRONT_PROBE_BED_POSITION),
  3223. back_probe_bed_position = code_seen('B') ? (int)code_value_axis_units(Y_AXIS) : LOGICAL_Y_POSITION(BACK_PROBE_BED_POSITION);
  3224. bool left_out_l = left_probe_bed_position < LOGICAL_X_POSITION(MIN_PROBE_X),
  3225. left_out = left_out_l || left_probe_bed_position > right_probe_bed_position - (MIN_PROBE_EDGE),
  3226. right_out_r = right_probe_bed_position > LOGICAL_X_POSITION(MAX_PROBE_X),
  3227. right_out = right_out_r || right_probe_bed_position < left_probe_bed_position + MIN_PROBE_EDGE,
  3228. front_out_f = front_probe_bed_position < LOGICAL_Y_POSITION(MIN_PROBE_Y),
  3229. front_out = front_out_f || front_probe_bed_position > back_probe_bed_position - (MIN_PROBE_EDGE),
  3230. back_out_b = back_probe_bed_position > LOGICAL_Y_POSITION(MAX_PROBE_Y),
  3231. back_out = back_out_b || back_probe_bed_position < front_probe_bed_position + MIN_PROBE_EDGE;
  3232. if (left_out || right_out || front_out || back_out) {
  3233. if (left_out) {
  3234. out_of_range_error(PSTR("(L)eft"));
  3235. left_probe_bed_position = left_out_l ? LOGICAL_X_POSITION(MIN_PROBE_X) : right_probe_bed_position - (MIN_PROBE_EDGE);
  3236. }
  3237. if (right_out) {
  3238. out_of_range_error(PSTR("(R)ight"));
  3239. right_probe_bed_position = right_out_r ? LOGICAL_Y_POSITION(MAX_PROBE_X) : left_probe_bed_position + MIN_PROBE_EDGE;
  3240. }
  3241. if (front_out) {
  3242. out_of_range_error(PSTR("(F)ront"));
  3243. front_probe_bed_position = front_out_f ? LOGICAL_Y_POSITION(MIN_PROBE_Y) : back_probe_bed_position - (MIN_PROBE_EDGE);
  3244. }
  3245. if (back_out) {
  3246. out_of_range_error(PSTR("(B)ack"));
  3247. back_probe_bed_position = back_out_b ? LOGICAL_Y_POSITION(MAX_PROBE_Y) : front_probe_bed_position + MIN_PROBE_EDGE;
  3248. }
  3249. return;
  3250. }
  3251. #endif // ABL_GRID
  3252. stepper.synchronize();
  3253. // Disable auto bed leveling during G29
  3254. bool abl_should_enable = planner.abl_enabled;
  3255. planner.abl_enabled = false;
  3256. if (!dryrun) {
  3257. // Re-orient the current position without leveling
  3258. // based on where the steppers are positioned.
  3259. set_current_from_steppers_for_axis(ALL_AXES);
  3260. // Sync the planner to where the steppers stopped
  3261. planner.sync_from_steppers();
  3262. }
  3263. setup_for_endstop_or_probe_move();
  3264. // Deploy the probe. Probe will raise if needed.
  3265. if (DEPLOY_PROBE()) {
  3266. planner.abl_enabled = abl_should_enable;
  3267. return;
  3268. }
  3269. float xProbe = 0, yProbe = 0, measured_z = 0;
  3270. #if ABL_GRID
  3271. // probe at the points of a lattice grid
  3272. const float xGridSpacing = (right_probe_bed_position - left_probe_bed_position) / (abl_grid_points_x - 1),
  3273. yGridSpacing = (back_probe_bed_position - front_probe_bed_position) / (abl_grid_points_y - 1);
  3274. #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
  3275. float zoffset = zprobe_zoffset;
  3276. if (code_seen('Z')) zoffset += code_value_axis_units(Z_AXIS);
  3277. if ( xGridSpacing != bilinear_grid_spacing[X_AXIS]
  3278. || yGridSpacing != bilinear_grid_spacing[Y_AXIS]
  3279. || left_probe_bed_position != bilinear_start[X_AXIS]
  3280. || front_probe_bed_position != bilinear_start[Y_AXIS]
  3281. ) {
  3282. bilinear_grid_spacing[X_AXIS] = xGridSpacing;
  3283. bilinear_grid_spacing[Y_AXIS] = yGridSpacing;
  3284. bilinear_start[X_AXIS] = RAW_X_POSITION(left_probe_bed_position);
  3285. bilinear_start[Y_AXIS] = RAW_Y_POSITION(front_probe_bed_position);
  3286. // Can't re-enable (on error) until the new grid is written
  3287. abl_should_enable = false;
  3288. }
  3289. #elif ENABLED(AUTO_BED_LEVELING_LINEAR)
  3290. /**
  3291. * solve the plane equation ax + by + d = z
  3292. * A is the matrix with rows [x y 1] for all the probed points
  3293. * B is the vector of the Z positions
  3294. * the normal vector to the plane is formed by the coefficients of the
  3295. * plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0
  3296. * so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z
  3297. */
  3298. int abl2 = abl_grid_points_x * abl_grid_points_y,
  3299. indexIntoAB[abl_grid_points_x][abl_grid_points_y],
  3300. probePointCounter = -1;
  3301. float eqnAMatrix[abl2 * 3], // "A" matrix of the linear system of equations
  3302. eqnBVector[abl2], // "B" vector of Z points
  3303. mean = 0.0;
  3304. #endif // AUTO_BED_LEVELING_LINEAR
  3305. #if ENABLED(PROBE_Y_FIRST)
  3306. #define PR_OUTER_VAR xCount
  3307. #define PR_OUTER_END abl_grid_points_x
  3308. #define PR_INNER_VAR yCount
  3309. #define PR_INNER_END abl_grid_points_y
  3310. #else
  3311. #define PR_OUTER_VAR yCount
  3312. #define PR_OUTER_END abl_grid_points_y
  3313. #define PR_INNER_VAR xCount
  3314. #define PR_INNER_END abl_grid_points_x
  3315. #endif
  3316. #if ENABLED(MAKERARM_SCARA)
  3317. bool zig = true;
  3318. #else
  3319. bool zig = PR_OUTER_END & 1; //always end at [RIGHT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION]
  3320. #endif
  3321. for (uint8_t PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_END; PR_OUTER_VAR++) {
  3322. int8_t inStart, inStop, inInc;
  3323. if (zig) {
  3324. inStart = 0;
  3325. inStop = PR_INNER_END;
  3326. inInc = 1;
  3327. }
  3328. else {
  3329. inStart = PR_INNER_END - 1;
  3330. inStop = -1;
  3331. inInc = -1;
  3332. }
  3333. zig = !zig;
  3334. for (int8_t PR_INNER_VAR = inStart; PR_INNER_VAR != inStop; PR_INNER_VAR += inInc) {
  3335. float xBase = left_probe_bed_position + xGridSpacing * xCount,
  3336. yBase = front_probe_bed_position + yGridSpacing * yCount;
  3337. xProbe = floor(xBase + (xBase < 0 ? 0 : 0.5));
  3338. yProbe = floor(yBase + (yBase < 0 ? 0 : 0.5));
  3339. #if ENABLED(AUTO_BED_LEVELING_LINEAR)
  3340. indexIntoAB[xCount][yCount] = ++probePointCounter;
  3341. #endif
  3342. #if IS_KINEMATIC
  3343. // Avoid probing outside the round or hexagonal area
  3344. float pos[XYZ] = { xProbe, yProbe, 0 };
  3345. if (!position_is_reachable(pos, true)) continue;
  3346. #endif
  3347. measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
  3348. if (measured_z == NAN) {
  3349. planner.abl_enabled = abl_should_enable;
  3350. return;
  3351. }
  3352. #if ENABLED(AUTO_BED_LEVELING_LINEAR)
  3353. mean += measured_z;
  3354. eqnBVector[probePointCounter] = measured_z;
  3355. eqnAMatrix[probePointCounter + 0 * abl2] = xProbe;
  3356. eqnAMatrix[probePointCounter + 1 * abl2] = yProbe;
  3357. eqnAMatrix[probePointCounter + 2 * abl2] = 1;
  3358. #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
  3359. bed_level_grid[xCount][yCount] = measured_z + zoffset;
  3360. #endif
  3361. idle();
  3362. } //xProbe
  3363. } //yProbe
  3364. #elif ENABLED(AUTO_BED_LEVELING_3POINT)
  3365. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3366. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> 3-point Leveling");
  3367. #endif
  3368. // Probe at 3 arbitrary points
  3369. vector_3 points[3] = {
  3370. vector_3(ABL_PROBE_PT_1_X, ABL_PROBE_PT_1_Y, 0),
  3371. vector_3(ABL_PROBE_PT_2_X, ABL_PROBE_PT_2_Y, 0),
  3372. vector_3(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, 0)
  3373. };
  3374. for (uint8_t i = 0; i < 3; ++i) {
  3375. // Retain the last probe position
  3376. xProbe = LOGICAL_X_POSITION(points[i].x);
  3377. yProbe = LOGICAL_Y_POSITION(points[i].y);
  3378. measured_z = points[i].z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
  3379. }
  3380. if (measured_z == NAN) {
  3381. planner.abl_enabled = abl_should_enable;
  3382. return;
  3383. }
  3384. if (!dryrun) {
  3385. vector_3 planeNormal = vector_3::cross(points[0] - points[1], points[2] - points[1]).get_normal();
  3386. if (planeNormal.z < 0) {
  3387. planeNormal.x *= -1;
  3388. planeNormal.y *= -1;
  3389. planeNormal.z *= -1;
  3390. }
  3391. planner.bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
  3392. // Can't re-enable (on error) until the new grid is written
  3393. abl_should_enable = false;
  3394. }
  3395. #endif // AUTO_BED_LEVELING_3POINT
  3396. // Raise to _Z_CLEARANCE_DEPLOY_PROBE. Stow the probe.
  3397. if (STOW_PROBE()) {
  3398. planner.abl_enabled = abl_should_enable;
  3399. return;
  3400. }
  3401. //
  3402. // Unless this is a dry run, auto bed leveling will
  3403. // definitely be enabled after this point
  3404. //
  3405. // Restore state after probing
  3406. clean_up_after_endstop_or_probe_move();
  3407. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3408. if (DEBUGGING(LEVELING)) DEBUG_POS("> probing complete", current_position);
  3409. #endif
  3410. // Calculate leveling, print reports, correct the position
  3411. #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
  3412. if (!dryrun) extrapolate_unprobed_bed_level();
  3413. print_bed_level();
  3414. #elif ENABLED(AUTO_BED_LEVELING_LINEAR)
  3415. // For LINEAR leveling calculate matrix, print reports, correct the position
  3416. // solve lsq problem
  3417. float plane_equation_coefficients[3];
  3418. qr_solve(plane_equation_coefficients, abl2, 3, eqnAMatrix, eqnBVector);
  3419. mean /= abl2;
  3420. if (verbose_level) {
  3421. SERIAL_PROTOCOLPGM("Eqn coefficients: a: ");
  3422. SERIAL_PROTOCOL_F(plane_equation_coefficients[0], 8);
  3423. SERIAL_PROTOCOLPGM(" b: ");
  3424. SERIAL_PROTOCOL_F(plane_equation_coefficients[1], 8);
  3425. SERIAL_PROTOCOLPGM(" d: ");
  3426. SERIAL_PROTOCOL_F(plane_equation_coefficients[2], 8);
  3427. SERIAL_EOL;
  3428. if (verbose_level > 2) {
  3429. SERIAL_PROTOCOLPGM("Mean of sampled points: ");
  3430. SERIAL_PROTOCOL_F(mean, 8);
  3431. SERIAL_EOL;
  3432. }
  3433. }
  3434. // Create the matrix but don't correct the position yet
  3435. if (!dryrun) {
  3436. planner.bed_level_matrix = matrix_3x3::create_look_at(
  3437. vector_3(-plane_equation_coefficients[0], -plane_equation_coefficients[1], 1)
  3438. );
  3439. }
  3440. // Show the Topography map if enabled
  3441. if (do_topography_map) {
  3442. SERIAL_PROTOCOLLNPGM("\nBed Height Topography:\n"
  3443. " +--- BACK --+\n"
  3444. " | |\n"
  3445. " L | (+) | R\n"
  3446. " E | | I\n"
  3447. " F | (-) N (+) | G\n"
  3448. " T | | H\n"
  3449. " | (-) | T\n"
  3450. " | |\n"
  3451. " O-- FRONT --+\n"
  3452. " (0,0)");
  3453. float min_diff = 999;
  3454. for (int8_t yy = abl_grid_points_y - 1; yy >= 0; yy--) {
  3455. for (uint8_t xx = 0; xx < abl_grid_points_x; xx++) {
  3456. int ind = indexIntoAB[xx][yy];
  3457. float diff = eqnBVector[ind] - mean,
  3458. x_tmp = eqnAMatrix[ind + 0 * abl2],
  3459. y_tmp = eqnAMatrix[ind + 1 * abl2],
  3460. z_tmp = 0;
  3461. apply_rotation_xyz(planner.bed_level_matrix, x_tmp, y_tmp, z_tmp);
  3462. NOMORE(min_diff, eqnBVector[ind] - z_tmp);
  3463. if (diff >= 0.0)
  3464. SERIAL_PROTOCOLPGM(" +"); // Include + for column alignment
  3465. else
  3466. SERIAL_PROTOCOLCHAR(' ');
  3467. SERIAL_PROTOCOL_F(diff, 5);
  3468. } // xx
  3469. SERIAL_EOL;
  3470. } // yy
  3471. SERIAL_EOL;
  3472. if (verbose_level > 3) {
  3473. SERIAL_PROTOCOLLNPGM("\nCorrected Bed Height vs. Bed Topology:");
  3474. for (int8_t yy = abl_grid_points_y - 1; yy >= 0; yy--) {
  3475. for (uint8_t xx = 0; xx < abl_grid_points_x; xx++) {
  3476. int ind = indexIntoAB[xx][yy];
  3477. float x_tmp = eqnAMatrix[ind + 0 * abl2],
  3478. y_tmp = eqnAMatrix[ind + 1 * abl2],
  3479. z_tmp = 0;
  3480. apply_rotation_xyz(planner.bed_level_matrix, x_tmp, y_tmp, z_tmp);
  3481. float diff = eqnBVector[ind] - z_tmp - min_diff;
  3482. if (diff >= 0.0)
  3483. SERIAL_PROTOCOLPGM(" +");
  3484. // Include + for column alignment
  3485. else
  3486. SERIAL_PROTOCOLCHAR(' ');
  3487. SERIAL_PROTOCOL_F(diff, 5);
  3488. } // xx
  3489. SERIAL_EOL;
  3490. } // yy
  3491. SERIAL_EOL;
  3492. }
  3493. } //do_topography_map
  3494. #endif // AUTO_BED_LEVELING_LINEAR
  3495. #if ABL_PLANAR
  3496. // For LINEAR and 3POINT leveling correct the current position
  3497. if (verbose_level > 0)
  3498. planner.bed_level_matrix.debug("\n\nBed Level Correction Matrix:");
  3499. if (!dryrun) {
  3500. //
  3501. // Correct the current XYZ position based on the tilted plane.
  3502. //
  3503. // 1. Get the distance from the current position to the reference point.
  3504. float x_dist = RAW_CURRENT_POSITION(X_AXIS) - X_TILT_FULCRUM,
  3505. y_dist = RAW_CURRENT_POSITION(Y_AXIS) - Y_TILT_FULCRUM,
  3506. z_real = current_position[Z_AXIS],
  3507. z_zero = 0;
  3508. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3509. if (DEBUGGING(LEVELING)) DEBUG_POS("G29 uncorrected XYZ", current_position);
  3510. #endif
  3511. matrix_3x3 inverse = matrix_3x3::transpose(planner.bed_level_matrix);
  3512. // 2. Apply the inverse matrix to the distance
  3513. // from the reference point to X, Y, and zero.
  3514. apply_rotation_xyz(inverse, x_dist, y_dist, z_zero);
  3515. // 3. Get the matrix-based corrected Z.
  3516. // (Even if not used, get it for comparison.)
  3517. float new_z = z_real + z_zero;
  3518. // 4. Use the last measured distance to the bed, if possible
  3519. if ( NEAR(current_position[X_AXIS], xProbe - (X_PROBE_OFFSET_FROM_EXTRUDER))
  3520. && NEAR(current_position[Y_AXIS], yProbe - (Y_PROBE_OFFSET_FROM_EXTRUDER))
  3521. ) {
  3522. float simple_z = z_real - (measured_z - (-zprobe_zoffset));
  3523. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3524. if (DEBUGGING(LEVELING)) {
  3525. SERIAL_ECHOPAIR("Z from Probe:", simple_z);
  3526. SERIAL_ECHOPAIR(" Matrix:", new_z);
  3527. SERIAL_ECHOLNPAIR(" Discrepancy:", simple_z - new_z);
  3528. }
  3529. #endif
  3530. new_z = simple_z;
  3531. }
  3532. // 5. The rotated XY and corrected Z are now current_position
  3533. current_position[X_AXIS] = LOGICAL_X_POSITION(x_dist) + X_TILT_FULCRUM;
  3534. current_position[Y_AXIS] = LOGICAL_Y_POSITION(y_dist) + Y_TILT_FULCRUM;
  3535. current_position[Z_AXIS] = new_z;
  3536. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3537. if (DEBUGGING(LEVELING)) DEBUG_POS("G29 corrected XYZ", current_position);
  3538. #endif
  3539. }
  3540. #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
  3541. if (!dryrun) {
  3542. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3543. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPAIR("G29 uncorrected Z:", current_position[Z_AXIS]);
  3544. #endif
  3545. // Unapply the offset because it is going to be immediately applied
  3546. // and cause compensation movement in Z
  3547. current_position[Z_AXIS] -= bilinear_z_offset(current_position);
  3548. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3549. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPAIR(" corrected Z:", current_position[Z_AXIS]);
  3550. #endif
  3551. }
  3552. #endif // ABL_PLANAR
  3553. #ifdef Z_PROBE_END_SCRIPT
  3554. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3555. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPAIR("Z Probe End Script: ", Z_PROBE_END_SCRIPT);
  3556. #endif
  3557. enqueue_and_echo_commands_P(PSTR(Z_PROBE_END_SCRIPT));
  3558. stepper.synchronize();
  3559. #endif
  3560. #if ENABLED(DEBUG_LEVELING_FEATURE)
  3561. if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< gcode_G29");
  3562. #endif
  3563. report_current_position();
  3564. KEEPALIVE_STATE(IN_HANDLER);
  3565. // Auto Bed Leveling is complete! Enable if possible.
  3566. planner.abl_enabled = dryrun ? abl_should_enable : true;
  3567. if (planner.abl_enabled)
  3568. SYNC_PLAN_POSITION_KINEMATIC();
  3569. }
  3570. #endif // HAS_ABL
  3571. #if HAS_BED_PROBE
  3572. /**
  3573. * G30: Do a single Z probe at the current XY
  3574. */
  3575. inline void gcode_G30() {
  3576. // Disable leveling so the planner won't mess with us
  3577. #if PLANNER_LEVELING
  3578. set_bed_leveling_enabled(false);
  3579. #endif
  3580. setup_for_endstop_or_probe_move();
  3581. float measured_z = probe_pt(current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER,
  3582. current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER,
  3583. true, 1);
  3584. SERIAL_PROTOCOLPGM("Bed X: ");
  3585. SERIAL_PROTOCOL(current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER + 0.0001);
  3586. SERIAL_PROTOCOLPGM(" Y: ");
  3587. SERIAL_PROTOCOL(current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER + 0.0001);
  3588. SERIAL_PROTOCOLPGM(" Z: ");
  3589. SERIAL_PROTOCOL(measured_z + 0.0001);
  3590. SERIAL_EOL;
  3591. clean_up_after_endstop_or_probe_move();
  3592. report_current_position();
  3593. }
  3594. #if ENABLED(Z_PROBE_SLED)
  3595. /**
  3596. * G31: Deploy the Z probe
  3597. */
  3598. inline void gcode_G31() { DEPLOY_PROBE(); }
  3599. /**
  3600. * G32: Stow the Z probe
  3601. */
  3602. inline void gcode_G32() { STOW_PROBE(); }
  3603. #endif // Z_PROBE_SLED
  3604. #endif // HAS_BED_PROBE
  3605. #ifdef G38_2_3
  3606. inline void gcode_G38(float code_num) {
  3607. #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) || ENABLED(Z_MIN_PROBE_ENDSTOP) //must have valid Z_MIN_PROBE definition for this command to work
  3608. if ((code_num == 38.2 || code_num == 38.3 ) && (code_seen('X') || code_seen('Y') || code_seen('Z'))) {
  3609. gcode_get_destination(); // For X Y Z E F
  3610. if (check_move()) { // see if the commanded movement will result in a physical movement
  3611. bool G38_pass_fail = false;
  3612. G38_run_probe(&G38_pass_fail);
  3613. if (!G38_pass_fail && (code_num == 38.2) ) SERIAL_PROTOCOLLNPGM(" ERROR - failed to reach target ");
  3614. }
  3615. }
  3616. }
  3617. #else
  3618. SERIAL_PROTOCOLLNPGM(" ERROR - Z_MIN_PROBE must be enabled ");
  3619. }
  3620. #endif
  3621. #endif //G38_2_3
  3622. /**
  3623. * G92: Set current position to given X Y Z E
  3624. */
  3625. inline void gcode_G92() {
  3626. bool didXYZ = false,
  3627. didE = code_seen('E');
  3628. if (!didE) stepper.synchronize();
  3629. LOOP_XYZE(i) {
  3630. if (code_seen(axis_codes[i])) {
  3631. #if IS_SCARA
  3632. current_position[i] = code_value_axis_units(i);
  3633. if (i != E_AXIS) didXYZ = true;
  3634. #else
  3635. float p = current_position[i],
  3636. v = code_value_axis_units(i);
  3637. current_position[i] = v;
  3638. if (i != E_AXIS) {
  3639. didXYZ = true;
  3640. position_shift[i] += v - p; // Offset the coordinate space
  3641. update_software_endstops((AxisEnum)i);
  3642. }
  3643. #endif
  3644. }
  3645. }
  3646. if (didXYZ)
  3647. SYNC_PLAN_POSITION_KINEMATIC();
  3648. else if (didE)
  3649. sync_plan_position_e();
  3650. report_current_position();
  3651. }
  3652. #if ENABLED(ULTIPANEL) || ENABLED(EMERGENCY_PARSER)
  3653. /**
  3654. * M0: Unconditional stop - Wait for user button press on LCD
  3655. * M1: Conditional stop - Wait for user button press on LCD
  3656. */
  3657. inline void gcode_M0_M1() {
  3658. char* args = current_command_args;
  3659. millis_t codenum = 0;
  3660. bool hasP = false, hasS = false;
  3661. if (code_seen('P')) {
  3662. codenum = code_value_millis(); // milliseconds to wait
  3663. hasP = codenum > 0;
  3664. }
  3665. if (code_seen('S')) {
  3666. codenum = code_value_millis_from_seconds(); // seconds to wait
  3667. hasS = codenum > 0;
  3668. }
  3669. #if ENABLED(ULTIPANEL)
  3670. if (!hasP && !hasS && *args != '\0')
  3671. lcd_setstatus(args, true);
  3672. else {
  3673. LCD_MESSAGEPGM(MSG_USERWAIT);
  3674. #if ENABLED(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
  3675. dontExpireStatus();
  3676. #endif
  3677. }
  3678. lcd_ignore_click();
  3679. #else
  3680. if (!hasP && !hasS && *args != '\0') {
  3681. SERIAL_ECHO_START;
  3682. SERIAL_ECHOLN(args);
  3683. }
  3684. #endif
  3685. stepper.synchronize();
  3686. refresh_cmd_timeout();
  3687. #if ENABLED(ULTIPANEL)
  3688. if (codenum > 0) {
  3689. codenum += previous_cmd_ms; // wait until this time for a click
  3690. KEEPALIVE_STATE(PAUSED_FOR_USER);
  3691. while (PENDING(millis(), codenum) && !lcd_clicked()) idle();
  3692. lcd_ignore_click(false);
  3693. }
  3694. else if (lcd_detected()) {
  3695. KEEPALIVE_STATE(PAUSED_FOR_USER);
  3696. while (!lcd_clicked()) idle();
  3697. }
  3698. else return;
  3699. if (IS_SD_PRINTING)
  3700. LCD_MESSAGEPGM(MSG_RESUMING);
  3701. else
  3702. LCD_MESSAGEPGM(WELCOME_MSG);
  3703. #else
  3704. KEEPALIVE_STATE(PAUSED_FOR_USER);
  3705. wait_for_user = true;
  3706. if (codenum > 0) {
  3707. codenum += previous_cmd_ms; // wait until this time for an M108
  3708. while (PENDING(millis(), codenum) && wait_for_user) idle();
  3709. }
  3710. else while (wait_for_user) idle();
  3711. wait_for_user = false;
  3712. #endif
  3713. KEEPALIVE_STATE(IN_HANDLER);
  3714. }
  3715. #endif // ULTIPANEL || EMERGENCY_PARSER
  3716. /**
  3717. * M17: Enable power on all stepper motors
  3718. */
  3719. inline void gcode_M17() {
  3720. LCD_MESSAGEPGM(MSG_NO_MOVE);
  3721. enable_all_steppers();
  3722. }
  3723. #if ENABLED(SDSUPPORT)
  3724. /**
  3725. * M20: List SD card to serial output
  3726. */
  3727. inline void gcode_M20() {
  3728. SERIAL_PROTOCOLLNPGM(MSG_BEGIN_FILE_LIST);
  3729. card.ls();
  3730. SERIAL_PROTOCOLLNPGM(MSG_END_FILE_LIST);
  3731. }
  3732. /**
  3733. * M21: Init SD Card
  3734. */
  3735. inline void gcode_M21() { card.initsd(); }
  3736. /**
  3737. * M22: Release SD Card
  3738. */
  3739. inline void gcode_M22() { card.release(); }
  3740. /**
  3741. * M23: Open a file
  3742. */
  3743. inline void gcode_M23() { card.openFile(current_command_args, true); }
  3744. /**
  3745. * M24: Start SD Print
  3746. */
  3747. inline void gcode_M24() {
  3748. card.startFileprint();
  3749. print_job_timer.start();
  3750. }
  3751. /**
  3752. * M25: Pause SD Print
  3753. */
  3754. inline void gcode_M25() { card.pauseSDPrint(); }
  3755. /**
  3756. * M26: Set SD Card file index
  3757. */
  3758. inline void gcode_M26() {
  3759. if (card.cardOK && code_seen('S'))
  3760. card.setIndex(code_value_long());
  3761. }
  3762. /**
  3763. * M27: Get SD Card status
  3764. */
  3765. inline void gcode_M27() { card.getStatus(); }
  3766. /**
  3767. * M28: Start SD Write
  3768. */
  3769. inline void gcode_M28() { card.openFile(current_command_args, false); }
  3770. /**
  3771. * M29: Stop SD Write
  3772. * Processed in write to file routine above
  3773. */
  3774. inline void gcode_M29() {
  3775. // card.saving = false;
  3776. }
  3777. /**
  3778. * M30 <filename>: Delete SD Card file
  3779. */
  3780. inline void gcode_M30() {
  3781. if (card.cardOK) {
  3782. card.closefile();
  3783. card.removeFile(current_command_args);
  3784. }
  3785. }
  3786. #endif // SDSUPPORT
  3787. /**
  3788. * M31: Get the time since the start of SD Print (or last M109)
  3789. */
  3790. inline void gcode_M31() {
  3791. char buffer[21];
  3792. duration_t elapsed = print_job_timer.duration();
  3793. elapsed.toString(buffer);
  3794. lcd_setstatus(buffer);
  3795. SERIAL_ECHO_START;
  3796. SERIAL_ECHOLNPAIR("Print time: ", buffer);
  3797. thermalManager.autotempShutdown();
  3798. }
  3799. #if ENABLED(SDSUPPORT)
  3800. /**
  3801. * M32: Select file and start SD Print
  3802. */
  3803. inline void gcode_M32() {
  3804. if (card.sdprinting)
  3805. stepper.synchronize();
  3806. char* namestartpos = strchr(current_command_args, '!'); // Find ! to indicate filename string start.
  3807. if (!namestartpos)
  3808. namestartpos = current_command_args; // Default name position, 4 letters after the M
  3809. else
  3810. namestartpos++; //to skip the '!'
  3811. bool call_procedure = code_seen('P') && (seen_pointer < namestartpos);
  3812. if (card.cardOK) {
  3813. card.openFile(namestartpos, true, call_procedure);
  3814. if (code_seen('S') && seen_pointer < namestartpos) // "S" (must occur _before_ the filename!)
  3815. card.setIndex(code_value_long());
  3816. card.startFileprint();
  3817. // Procedure calls count as normal print time.
  3818. if (!call_procedure) print_job_timer.start();
  3819. }
  3820. }
  3821. #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
  3822. /**
  3823. * M33: Get the long full path of a file or folder
  3824. *
  3825. * Parameters:
  3826. * <dospath> Case-insensitive DOS-style path to a file or folder
  3827. *
  3828. * Example:
  3829. * M33 miscel~1/armchair/armcha~1.gco
  3830. *
  3831. * Output:
  3832. * /Miscellaneous/Armchair/Armchair.gcode
  3833. */
  3834. inline void gcode_M33() {
  3835. card.printLongPath(current_command_args);
  3836. }
  3837. #endif
  3838. /**
  3839. * M928: Start SD Write
  3840. */
  3841. inline void gcode_M928() {
  3842. card.openLogFile(current_command_args);
  3843. }
  3844. #endif // SDSUPPORT
  3845. /**
  3846. * M42: Change pin status via GCode
  3847. *
  3848. * P<pin> Pin number (LED if omitted)
  3849. * S<byte> Pin status from 0 - 255
  3850. */
  3851. inline void gcode_M42() {
  3852. if (!code_seen('S')) return;
  3853. int pin_status = code_value_int();
  3854. if (pin_status < 0 || pin_status > 255) return;
  3855. int pin_number = code_seen('P') ? code_value_int() : LED_PIN;
  3856. if (pin_number < 0) return;
  3857. for (uint8_t i = 0; i < COUNT(sensitive_pins); i++)
  3858. if (pin_number == sensitive_pins[i]) {
  3859. SERIAL_ERROR_START;
  3860. SERIAL_ERRORLNPGM(MSG_ERR_PROTECTED_PIN);
  3861. return;
  3862. }
  3863. pinMode(pin_number, OUTPUT);
  3864. digitalWrite(pin_number, pin_status);
  3865. analogWrite(pin_number, pin_status);
  3866. #if FAN_COUNT > 0
  3867. switch (pin_number) {
  3868. #if HAS_FAN0
  3869. case FAN_PIN: fanSpeeds[0] = pin_status; break;
  3870. #endif
  3871. #if HAS_FAN1
  3872. case FAN1_PIN: fanSpeeds[1] = pin_status; break;
  3873. #endif
  3874. #if HAS_FAN2
  3875. case FAN2_PIN: fanSpeeds[2] = pin_status; break;
  3876. #endif
  3877. }
  3878. #endif
  3879. }
  3880. #if ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST)
  3881. /**
  3882. * M48: Z probe repeatability measurement function.
  3883. *
  3884. * Usage:
  3885. * M48 <P#> <X#> <Y#> <V#> <E> <L#>
  3886. * P = Number of sampled points (4-50, default 10)
  3887. * X = Sample X position
  3888. * Y = Sample Y position
  3889. * V = Verbose level (0-4, default=1)
  3890. * E = Engage Z probe for each reading
  3891. * L = Number of legs of movement before probe
  3892. * S = Schizoid (Or Star if you prefer)
  3893. *
  3894. * This function assumes the bed has been homed. Specifically, that a G28 command
  3895. * as been issued prior to invoking the M48 Z probe repeatability measurement function.
  3896. * Any information generated by a prior G29 Bed leveling command will be lost and need to be
  3897. * regenerated.
  3898. */
  3899. inline void gcode_M48() {
  3900. if (axis_unhomed_error(true, true, true)) return;
  3901. int8_t verbose_level = code_seen('V') ? code_value_byte() : 1;
  3902. if (verbose_level < 0 || verbose_level > 4) {
  3903. SERIAL_PROTOCOLLNPGM("?Verbose Level not plausible (0-4).");
  3904. return;
  3905. }
  3906. if (verbose_level > 0)
  3907. SERIAL_PROTOCOLLNPGM("M48 Z-Probe Repeatability test");
  3908. int8_t n_samples = code_seen('P') ? code_value_byte() : 10;
  3909. if (n_samples < 4 || n_samples > 50) {
  3910. SERIAL_PROTOCOLLNPGM("?Sample size not plausible (4-50).");
  3911. return;
  3912. }
  3913. float X_current = current_position[X_AXIS],
  3914. Y_current = current_position[Y_AXIS];
  3915. bool stow_probe_after_each = code_seen('E');
  3916. float X_probe_location = code_seen('X') ? code_value_axis_units(X_AXIS) : X_current + X_PROBE_OFFSET_FROM_EXTRUDER;
  3917. #if DISABLED(DELTA)
  3918. if (X_probe_location < LOGICAL_X_POSITION(MIN_PROBE_X) || X_probe_location > LOGICAL_X_POSITION(MAX_PROBE_X)) {
  3919. out_of_range_error(PSTR("X"));
  3920. return;
  3921. }
  3922. #endif
  3923. float Y_probe_location = code_seen('Y') ? code_value_axis_units(Y_AXIS) : Y_current + Y_PROBE_OFFSET_FROM_EXTRUDER;
  3924. #if DISABLED(DELTA)
  3925. if (Y_probe_location < LOGICAL_Y_POSITION(MIN_PROBE_Y) || Y_probe_location > LOGICAL_Y_POSITION(MAX_PROBE_Y)) {
  3926. out_of_range_error(PSTR("Y"));
  3927. return;
  3928. }
  3929. #else
  3930. float pos[XYZ] = { X_probe_location, Y_probe_location, 0 };
  3931. if (!position_is_reachable(pos, true)) {
  3932. SERIAL_PROTOCOLLNPGM("? (X,Y) location outside of probeable radius.");
  3933. return;
  3934. }
  3935. #endif
  3936. bool seen_L = code_seen('L');
  3937. uint8_t n_legs = seen_L ? code_value_byte() : 0;
  3938. if (n_legs > 15) {
  3939. SERIAL_PROTOCOLLNPGM("?Number of legs in movement not plausible (0-15).");
  3940. return;
  3941. }
  3942. if (n_legs == 1) n_legs = 2;
  3943. bool schizoid_flag = code_seen('S');
  3944. if (schizoid_flag && !seen_L) n_legs = 7;
  3945. /**
  3946. * Now get everything to the specified probe point So we can safely do a
  3947. * probe to get us close to the bed. If the Z-Axis is far from the bed,
  3948. * we don't want to use that as a starting point for each probe.
  3949. */
  3950. if (verbose_level > 2)
  3951. SERIAL_PROTOCOLLNPGM("Positioning the probe...");
  3952. // Disable bed level correction in M48 because we want the raw data when we probe
  3953. #if HAS_ABL
  3954. reset_bed_level();
  3955. #endif
  3956. setup_for_endstop_or_probe_move();
  3957. // Move to the first point, deploy, and probe
  3958. probe_pt(X_probe_location, Y_probe_location, stow_probe_after_each, verbose_level);
  3959. randomSeed(millis());
  3960. double mean = 0, sigma = 0, sample_set[n_samples];
  3961. for (uint8_t n = 0; n < n_samples; n++) {
  3962. if (n_legs) {
  3963. int dir = (random(0, 10) > 5.0) ? -1 : 1; // clockwise or counter clockwise
  3964. float angle = random(0.0, 360.0),
  3965. radius = random(
  3966. #if ENABLED(DELTA)
  3967. DELTA_PROBEABLE_RADIUS / 8, DELTA_PROBEABLE_RADIUS / 3
  3968. #else
  3969. 5, X_MAX_LENGTH / 8
  3970. #endif
  3971. );
  3972. if (verbose_level > 3) {
  3973. SERIAL_ECHOPAIR("Starting radius: ", radius);
  3974. SERIAL_ECHOPAIR(" angle: ", angle);
  3975. SERIAL_ECHOPGM(" Direction: ");
  3976. if (dir > 0) SERIAL_ECHOPGM("Counter-");
  3977. SERIAL_ECHOLNPGM("Clockwise");
  3978. }
  3979. for (uint8_t l = 0; l < n_legs - 1; l++) {
  3980. double delta_angle;
  3981. if (schizoid_flag)
  3982. // The points of a 5 point star are 72 degrees apart. We need to
  3983. // skip a point and go to the next one on the star.
  3984. delta_angle = dir * 2.0 * 72.0;
  3985. else
  3986. // If we do this line, we are just trying to move further
  3987. // around the circle.
  3988. delta_angle = dir * (float) random(25, 45);
  3989. angle += delta_angle;
  3990. while (angle > 360.0) // We probably do not need to keep the angle between 0 and 2*PI, but the
  3991. angle -= 360.0; // Arduino documentation says the trig functions should not be given values
  3992. while (angle < 0.0) // outside of this range. It looks like they behave correctly with
  3993. angle += 360.0; // numbers outside of the range, but just to be safe we clamp them.
  3994. X_current = X_probe_location - (X_PROBE_OFFSET_FROM_EXTRUDER) + cos(RADIANS(angle)) * radius;
  3995. Y_current = Y_probe_location - (Y_PROBE_OFFSET_FROM_EXTRUDER) + sin(RADIANS(angle)) * radius;
  3996. #if DISABLED(DELTA)
  3997. X_current = constrain(X_current, X_MIN_POS, X_MAX_POS);
  3998. Y_current = constrain(Y_current, Y_MIN_POS, Y_MAX_POS);
  3999. #else
  4000. // If we have gone out too far, we can do a simple fix and scale the numbers
  4001. // back in closer to the origin.
  4002. while (HYPOT(X_current, Y_current) > DELTA_PROBEABLE_RADIUS) {
  4003. X_current /= 1.25;
  4004. Y_current /= 1.25;
  4005. if (verbose_level > 3) {
  4006. SERIAL_ECHOPAIR("Pulling point towards center:", X_current);
  4007. SERIAL_ECHOLNPAIR(", ", Y_current);
  4008. }
  4009. }
  4010. #endif
  4011. if (verbose_level > 3) {
  4012. SERIAL_PROTOCOLPGM("Going to:");
  4013. SERIAL_ECHOPAIR(" X", X_current);
  4014. SERIAL_ECHOPAIR(" Y", Y_current);
  4015. SERIAL_ECHOLNPAIR(" Z", current_position[Z_AXIS]);
  4016. }
  4017. do_blocking_move_to_xy(X_current, Y_current);
  4018. } // n_legs loop
  4019. } // n_legs
  4020. // Probe a single point
  4021. sample_set[n] = probe_pt(X_probe_location, Y_probe_location, stow_probe_after_each, verbose_level);
  4022. /**
  4023. * Get the current mean for the data points we have so far
  4024. */
  4025. double sum = 0.0;
  4026. for (uint8_t j = 0; j <= n; j++) sum += sample_set[j];
  4027. mean = sum / (n + 1);
  4028. /**
  4029. * Now, use that mean to calculate the standard deviation for the
  4030. * data points we have so far
  4031. */
  4032. sum = 0.0;
  4033. for (uint8_t j = 0; j <= n; j++)
  4034. sum += sq(sample_set[j] - mean);
  4035. sigma = sqrt(sum / (n + 1));
  4036. if (verbose_level > 0) {
  4037. if (verbose_level > 1) {
  4038. SERIAL_PROTOCOL(n + 1);
  4039. SERIAL_PROTOCOLPGM(" of ");
  4040. SERIAL_PROTOCOL((int)n_samples);
  4041. SERIAL_PROTOCOLPGM(" z: ");
  4042. SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6);
  4043. if (verbose_level > 2) {
  4044. SERIAL_PROTOCOLPGM(" mean: ");
  4045. SERIAL_PROTOCOL_F(mean, 6);
  4046. SERIAL_PROTOCOLPGM(" sigma: ");
  4047. SERIAL_PROTOCOL_F(sigma, 6);
  4048. }
  4049. }
  4050. SERIAL_EOL;
  4051. }
  4052. } // End of probe loop
  4053. if (STOW_PROBE()) return;
  4054. if (verbose_level > 0) {
  4055. SERIAL_PROTOCOLPGM("Mean: ");
  4056. SERIAL_PROTOCOL_F(mean, 6);
  4057. SERIAL_EOL;
  4058. }
  4059. SERIAL_PROTOCOLPGM("Standard Deviation: ");
  4060. SERIAL_PROTOCOL_F(sigma, 6);
  4061. SERIAL_EOL; SERIAL_EOL;
  4062. clean_up_after_endstop_or_probe_move();
  4063. report_current_position();
  4064. }
  4065. #endif // Z_MIN_PROBE_REPEATABILITY_TEST
  4066. /**
  4067. * M75: Start print timer
  4068. */
  4069. inline void gcode_M75() { print_job_timer.start(); }
  4070. /**
  4071. * M76: Pause print timer
  4072. */
  4073. inline void gcode_M76() { print_job_timer.pause(); }
  4074. /**
  4075. * M77: Stop print timer
  4076. */
  4077. inline void gcode_M77() { print_job_timer.stop(); }
  4078. #if ENABLED(PRINTCOUNTER)
  4079. /**
  4080. * M78: Show print statistics
  4081. */
  4082. inline void gcode_M78() {
  4083. // "M78 S78" will reset the statistics
  4084. if (code_seen('S') && code_value_int() == 78)
  4085. print_job_timer.initStats();
  4086. else
  4087. print_job_timer.showStats();
  4088. }
  4089. #endif
  4090. /**
  4091. * M104: Set hot end temperature
  4092. */
  4093. inline void gcode_M104() {
  4094. if (get_target_extruder_from_command(104)) return;
  4095. if (DEBUGGING(DRYRUN)) return;
  4096. #if ENABLED(SINGLENOZZLE)
  4097. if (target_extruder != active_extruder) return;
  4098. #endif
  4099. if (code_seen('S')) {
  4100. thermalManager.setTargetHotend(code_value_temp_abs(), target_extruder);
  4101. #if ENABLED(DUAL_X_CARRIAGE)
  4102. if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
  4103. thermalManager.setTargetHotend(code_value_temp_abs() == 0.0 ? 0.0 : code_value_temp_abs() + duplicate_extruder_temp_offset, 1);
  4104. #endif
  4105. #if ENABLED(PRINTJOB_TIMER_AUTOSTART)
  4106. /**
  4107. * Stop the timer at the end of print, starting is managed by
  4108. * 'heat and wait' M109.
  4109. * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
  4110. * stand by mode, for instance in a dual extruder setup, without affecting
  4111. * the running print timer.
  4112. */
  4113. if (code_value_temp_abs() <= (EXTRUDE_MINTEMP)/2) {
  4114. print_job_timer.stop();
  4115. LCD_MESSAGEPGM(WELCOME_MSG);
  4116. }
  4117. #endif
  4118. if (code_value_temp_abs() > thermalManager.degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
  4119. }
  4120. }
  4121. #if HAS_TEMP_HOTEND || HAS_TEMP_BED
  4122. void print_heaterstates() {
  4123. #if HAS_TEMP_HOTEND
  4124. SERIAL_PROTOCOLPGM(" T:");
  4125. SERIAL_PROTOCOL_F(thermalManager.degHotend(target_extruder), 1);
  4126. SERIAL_PROTOCOLPGM(" /");
  4127. SERIAL_PROTOCOL_F(thermalManager.degTargetHotend(target_extruder), 1);
  4128. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  4129. SERIAL_PROTOCOLPAIR(" (", thermalManager.current_temperature_raw[target_extruder] / OVERSAMPLENR);
  4130. SERIAL_CHAR(')');
  4131. #endif
  4132. #endif
  4133. #if HAS_TEMP_BED
  4134. SERIAL_PROTOCOLPGM(" B:");
  4135. SERIAL_PROTOCOL_F(thermalManager.degBed(), 1);
  4136. SERIAL_PROTOCOLPGM(" /");
  4137. SERIAL_PROTOCOL_F(thermalManager.degTargetBed(), 1);
  4138. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  4139. SERIAL_PROTOCOLPAIR(" (", thermalManager.current_temperature_bed_raw / OVERSAMPLENR);
  4140. SERIAL_CHAR(')');
  4141. #endif
  4142. #endif
  4143. #if HOTENDS > 1
  4144. HOTEND_LOOP() {
  4145. SERIAL_PROTOCOLPAIR(" T", e);
  4146. SERIAL_PROTOCOLCHAR(':');
  4147. SERIAL_PROTOCOL_F(thermalManager.degHotend(e), 1);
  4148. SERIAL_PROTOCOLPGM(" /");
  4149. SERIAL_PROTOCOL_F(thermalManager.degTargetHotend(e), 1);
  4150. #if ENABLED(SHOW_TEMP_ADC_VALUES)
  4151. SERIAL_PROTOCOLPAIR(" (", thermalManager.current_temperature_raw[e] / OVERSAMPLENR);
  4152. SERIAL_CHAR(')');
  4153. #endif
  4154. }
  4155. #endif
  4156. SERIAL_PROTOCOLPGM(" @:");
  4157. SERIAL_PROTOCOL(thermalManager.getHeaterPower(target_extruder));
  4158. #if HAS_TEMP_BED
  4159. SERIAL_PROTOCOLPGM(" B@:");
  4160. SERIAL_PROTOCOL(thermalManager.getHeaterPower(-1));
  4161. #endif
  4162. #if HOTENDS > 1
  4163. HOTEND_LOOP() {
  4164. SERIAL_PROTOCOLPAIR(" @", e);
  4165. SERIAL_PROTOCOLCHAR(':');
  4166. SERIAL_PROTOCOL(thermalManager.getHeaterPower(e));
  4167. }
  4168. #endif
  4169. }
  4170. #endif
  4171. /**
  4172. * M105: Read hot end and bed temperature
  4173. */
  4174. inline void gcode_M105() {
  4175. if (get_target_extruder_from_command(105)) return;
  4176. #if HAS_TEMP_HOTEND || HAS_TEMP_BED
  4177. SERIAL_PROTOCOLPGM(MSG_OK);
  4178. print_heaterstates();
  4179. #else // !HAS_TEMP_HOTEND && !HAS_TEMP_BED
  4180. SERIAL_ERROR_START;
  4181. SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
  4182. #endif
  4183. SERIAL_EOL;
  4184. }
  4185. #if FAN_COUNT > 0
  4186. /**
  4187. * M106: Set Fan Speed
  4188. *
  4189. * S<int> Speed between 0-255
  4190. * P<index> Fan index, if more than one fan
  4191. */
  4192. inline void gcode_M106() {
  4193. uint16_t s = code_seen('S') ? code_value_ushort() : 255,
  4194. p = code_seen('P') ? code_value_ushort() : 0;
  4195. NOMORE(s, 255);
  4196. if (p < FAN_COUNT) fanSpeeds[p] = s;
  4197. }
  4198. /**
  4199. * M107: Fan Off
  4200. */
  4201. inline void gcode_M107() {
  4202. uint16_t p = code_seen('P') ? code_value_ushort() : 0;
  4203. if (p < FAN_COUNT) fanSpeeds[p] = 0;
  4204. }
  4205. #endif // FAN_COUNT > 0
  4206. #if DISABLED(EMERGENCY_PARSER)
  4207. /**
  4208. * M108: Stop the waiting for heaters in M109, M190, M303. Does not affect the target temperature.
  4209. */
  4210. inline void gcode_M108() { wait_for_heatup = false; }
  4211. /**
  4212. * M112: Emergency Stop
  4213. */
  4214. inline void gcode_M112() { kill(PSTR(MSG_KILLED)); }
  4215. /**
  4216. * M410: Quickstop - Abort all planned moves
  4217. *
  4218. * This will stop the carriages mid-move, so most likely they
  4219. * will be out of sync with the stepper position after this.
  4220. */
  4221. inline void gcode_M410() { quickstop_stepper(); }
  4222. #endif
  4223. #ifndef MIN_COOLING_SLOPE_DEG
  4224. #define MIN_COOLING_SLOPE_DEG 1.50
  4225. #endif
  4226. #ifndef MIN_COOLING_SLOPE_TIME
  4227. #define MIN_COOLING_SLOPE_TIME 60
  4228. #endif
  4229. /**
  4230. * M109: Sxxx Wait for extruder(s) to reach temperature. Waits only when heating.
  4231. * Rxxx Wait for extruder(s) to reach temperature. Waits when heating and cooling.
  4232. */
  4233. inline void gcode_M109() {
  4234. if (get_target_extruder_from_command(109)) return;
  4235. if (DEBUGGING(DRYRUN)) return;
  4236. #if ENABLED(SINGLENOZZLE)
  4237. if (target_extruder != active_extruder) return;
  4238. #endif
  4239. bool no_wait_for_cooling = code_seen('S');
  4240. if (no_wait_for_cooling || code_seen('R')) {
  4241. thermalManager.setTargetHotend(code_value_temp_abs(), target_extruder);
  4242. #if ENABLED(DUAL_X_CARRIAGE)
  4243. if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
  4244. thermalManager.setTargetHotend(code_value_temp_abs() == 0.0 ? 0.0 : code_value_temp_abs() + duplicate_extruder_temp_offset, 1);
  4245. #endif
  4246. #if ENABLED(PRINTJOB_TIMER_AUTOSTART)
  4247. /**
  4248. * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
  4249. * stand by mode, for instance in a dual extruder setup, without affecting
  4250. * the running print timer.
  4251. */
  4252. if (code_value_temp_abs() <= (EXTRUDE_MINTEMP)/2) {
  4253. print_job_timer.stop();
  4254. LCD_MESSAGEPGM(WELCOME_MSG);
  4255. }
  4256. /**
  4257. * We do not check if the timer is already running because this check will
  4258. * be done for us inside the Stopwatch::start() method thus a running timer
  4259. * will not restart.
  4260. */
  4261. else print_job_timer.start();
  4262. #endif
  4263. if (thermalManager.isHeatingHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
  4264. }
  4265. #if ENABLED(AUTOTEMP)
  4266. planner.autotemp_M109();
  4267. #endif
  4268. #if TEMP_RESIDENCY_TIME > 0
  4269. millis_t residency_start_ms = 0;
  4270. // Loop until the temperature has stabilized
  4271. #define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL))
  4272. #else
  4273. // Loop until the temperature is very close target
  4274. #define TEMP_CONDITIONS (wants_to_cool ? thermalManager.isCoolingHotend(target_extruder) : thermalManager.isHeatingHotend(target_extruder))
  4275. #endif //TEMP_RESIDENCY_TIME > 0
  4276. float theTarget = -1.0, old_temp = 9999.0;
  4277. bool wants_to_cool = false;
  4278. wait_for_heatup = true;
  4279. millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;
  4280. KEEPALIVE_STATE(NOT_BUSY);
  4281. do {
  4282. // Target temperature might be changed during the loop
  4283. if (theTarget != thermalManager.degTargetHotend(target_extruder)) {
  4284. wants_to_cool = thermalManager.isCoolingHotend(target_extruder);
  4285. theTarget = thermalManager.degTargetHotend(target_extruder);
  4286. // Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
  4287. if (no_wait_for_cooling && wants_to_cool) break;
  4288. }
  4289. now = millis();
  4290. if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting
  4291. next_temp_ms = now + 1000UL;
  4292. print_heaterstates();
  4293. #if TEMP_RESIDENCY_TIME > 0
  4294. SERIAL_PROTOCOLPGM(" W:");
  4295. if (residency_start_ms) {
  4296. long rem = (((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL;
  4297. SERIAL_PROTOCOLLN(rem);
  4298. }
  4299. else {
  4300. SERIAL_PROTOCOLLNPGM("?");
  4301. }
  4302. #else
  4303. SERIAL_EOL;
  4304. #endif
  4305. }
  4306. idle();
  4307. refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
  4308. float temp = thermalManager.degHotend(target_extruder);
  4309. #if TEMP_RESIDENCY_TIME > 0
  4310. float temp_diff = fabs(theTarget - temp);
  4311. if (!residency_start_ms) {
  4312. // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
  4313. if (temp_diff < TEMP_WINDOW) residency_start_ms = now;
  4314. }
  4315. else if (temp_diff > TEMP_HYSTERESIS) {
  4316. // Restart the timer whenever the temperature falls outside the hysteresis.
  4317. residency_start_ms = now;
  4318. }
  4319. #endif //TEMP_RESIDENCY_TIME > 0
  4320. // Prevent a wait-forever situation if R is misused i.e. M109 R0
  4321. if (wants_to_cool) {
  4322. // break after MIN_COOLING_SLOPE_TIME seconds
  4323. // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG
  4324. if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) {
  4325. if (old_temp - temp < MIN_COOLING_SLOPE_DEG) break;
  4326. next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME;
  4327. old_temp = temp;
  4328. }
  4329. }
  4330. } while (wait_for_heatup && TEMP_CONDITIONS);
  4331. if (wait_for_heatup) LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
  4332. KEEPALIVE_STATE(IN_HANDLER);
  4333. }
  4334. #if HAS_TEMP_BED
  4335. #ifndef MIN_COOLING_SLOPE_DEG_BED
  4336. #define MIN_COOLING_SLOPE_DEG_BED 1.50
  4337. #endif
  4338. #ifndef MIN_COOLING_SLOPE_TIME_BED
  4339. #define MIN_COOLING_SLOPE_TIME_BED 60
  4340. #endif
  4341. /**
  4342. * M190: Sxxx Wait for bed current temp to reach target temp. Waits only when heating
  4343. * Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
  4344. */
  4345. inline void gcode_M190() {
  4346. if (DEBUGGING(DRYRUN)) return;
  4347. LCD_MESSAGEPGM(MSG_BED_HEATING);
  4348. bool no_wait_for_cooling = code_seen('S');
  4349. if (no_wait_for_cooling || code_seen('R')) {
  4350. thermalManager.setTargetBed(code_value_temp_abs());
  4351. #if ENABLED(PRINTJOB_TIMER_AUTOSTART)
  4352. if (code_value_temp_abs() > BED_MINTEMP) {
  4353. /**
  4354. * We start the timer when 'heating and waiting' command arrives, LCD
  4355. * functions never wait. Cooling down managed by extruders.
  4356. *
  4357. * We do not check if the timer is already running because this check will
  4358. * be done for us inside the Stopwatch::start() method thus a running timer
  4359. * will not restart.
  4360. */
  4361. print_job_timer.start();
  4362. }
  4363. #endif
  4364. }
  4365. #if TEMP_BED_RESIDENCY_TIME > 0
  4366. millis_t residency_start_ms = 0;
  4367. // Loop until the temperature has stabilized
  4368. #define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL))
  4369. #else
  4370. // Loop until the temperature is very close target
  4371. #define TEMP_BED_CONDITIONS (wants_to_cool ? thermalManager.isCoolingBed() : thermalManager.isHeatingBed())
  4372. #endif //TEMP_BED_RESIDENCY_TIME > 0
  4373. float theTarget = -1.0, old_temp = 9999.0;
  4374. bool wants_to_cool = false;
  4375. wait_for_heatup = true;
  4376. millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;
  4377. KEEPALIVE_STATE(NOT_BUSY);
  4378. target_extruder = active_extruder; // for print_heaterstates
  4379. do {
  4380. // Target temperature might be changed during the loop
  4381. if (theTarget != thermalManager.degTargetBed()) {
  4382. wants_to_cool = thermalManager.isCoolingBed();
  4383. theTarget = thermalManager.degTargetBed();
  4384. // Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
  4385. if (no_wait_for_cooling && wants_to_cool) break;
  4386. }
  4387. now = millis();
  4388. if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up.
  4389. next_temp_ms = now + 1000UL;
  4390. print_heaterstates();
  4391. #if TEMP_BED_RESIDENCY_TIME > 0
  4392. SERIAL_PROTOCOLPGM(" W:");
  4393. if (residency_start_ms) {
  4394. long rem = (((TEMP_BED_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL;
  4395. SERIAL_PROTOCOLLN(rem);
  4396. }
  4397. else {
  4398. SERIAL_PROTOCOLLNPGM("?");
  4399. }
  4400. #else
  4401. SERIAL_EOL;
  4402. #endif
  4403. }
  4404. idle();
  4405. refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
  4406. float temp = thermalManager.degBed();
  4407. #if TEMP_BED_RESIDENCY_TIME > 0
  4408. float temp_diff = fabs(theTarget - temp);
  4409. if (!residency_start_ms) {
  4410. // Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time.
  4411. if (temp_diff < TEMP_BED_WINDOW) residency_start_ms = now;
  4412. }
  4413. else if (temp_diff > TEMP_BED_HYSTERESIS) {
  4414. // Restart the timer whenever the temperature falls outside the hysteresis.
  4415. residency_start_ms = now;
  4416. }
  4417. #endif //TEMP_BED_RESIDENCY_TIME > 0
  4418. // Prevent a wait-forever situation if R is misused i.e. M190 R0
  4419. if (wants_to_cool) {
  4420. // break after MIN_COOLING_SLOPE_TIME_BED seconds
  4421. // if the temperature did not drop at least MIN_COOLING_SLOPE_DEG_BED
  4422. if (!next_cool_check_ms || ELAPSED(now, next_cool_check_ms)) {
  4423. if (old_temp - temp < MIN_COOLING_SLOPE_DEG_BED) break;
  4424. next_cool_check_ms = now + 1000UL * MIN_COOLING_SLOPE_TIME_BED;
  4425. old_temp = temp;
  4426. }
  4427. }
  4428. } while (wait_for_heatup && TEMP_BED_CONDITIONS);
  4429. if (wait_for_heatup) LCD_MESSAGEPGM(MSG_BED_DONE);
  4430. KEEPALIVE_STATE(IN_HANDLER);
  4431. }
  4432. #endif // HAS_TEMP_BED
  4433. /**
  4434. * M110: Set Current Line Number
  4435. */
  4436. inline void gcode_M110() {
  4437. if (code_seen('N')) gcode_N = code_value_long();
  4438. }
  4439. /**
  4440. * M111: Set the debug level
  4441. */
  4442. inline void gcode_M111() {
  4443. marlin_debug_flags = code_seen('S') ? code_value_byte() : (uint8_t) DEBUG_NONE;
  4444. const static char str_debug_1[] PROGMEM = MSG_DEBUG_ECHO;
  4445. const static char str_debug_2[] PROGMEM = MSG_DEBUG_INFO;
  4446. const static char str_debug_4[] PROGMEM = MSG_DEBUG_ERRORS;
  4447. const static char str_debug_8[] PROGMEM = MSG_DEBUG_DRYRUN;
  4448. const static char str_debug_16[] PROGMEM = MSG_DEBUG_COMMUNICATION;
  4449. #if ENABLED(DEBUG_LEVELING_FEATURE)
  4450. const static char str_debug_32[] PROGMEM = MSG_DEBUG_LEVELING;
  4451. #endif
  4452. const static char* const debug_strings[] PROGMEM = {
  4453. str_debug_1, str_debug_2, str_debug_4, str_debug_8, str_debug_16,
  4454. #if ENABLED(DEBUG_LEVELING_FEATURE)
  4455. str_debug_32
  4456. #endif
  4457. };
  4458. SERIAL_ECHO_START;
  4459. SERIAL_ECHOPGM(MSG_DEBUG_PREFIX);
  4460. if (marlin_debug_flags) {
  4461. uint8_t comma = 0;
  4462. for (uint8_t i = 0; i < COUNT(debug_strings); i++) {
  4463. if (TEST(marlin_debug_flags, i)) {
  4464. if (comma++) SERIAL_CHAR(',');
  4465. serialprintPGM((char*)pgm_read_word(&(debug_strings[i])));
  4466. }
  4467. }
  4468. }
  4469. else {
  4470. SERIAL_ECHOPGM(MSG_DEBUG_OFF);
  4471. }
  4472. SERIAL_EOL;
  4473. }
  4474. #if ENABLED(HOST_KEEPALIVE_FEATURE)
  4475. /**
  4476. * M113: Get or set Host Keepalive interval (0 to disable)
  4477. *
  4478. * S<seconds> Optional. Set the keepalive interval.
  4479. */
  4480. inline void gcode_M113() {
  4481. if (code_seen('S')) {
  4482. host_keepalive_interval = code_value_byte();
  4483. NOMORE(host_keepalive_interval, 60);
  4484. }
  4485. else {
  4486. SERIAL_ECHO_START;
  4487. SERIAL_ECHOLNPAIR("M113 S", (unsigned long)host_keepalive_interval);
  4488. }
  4489. }
  4490. #endif
  4491. #if ENABLED(BARICUDA)
  4492. #if HAS_HEATER_1
  4493. /**
  4494. * M126: Heater 1 valve open
  4495. */
  4496. inline void gcode_M126() { baricuda_valve_pressure = code_seen('S') ? code_value_byte() : 255; }
  4497. /**
  4498. * M127: Heater 1 valve close
  4499. */
  4500. inline void gcode_M127() { baricuda_valve_pressure = 0; }
  4501. #endif
  4502. #if HAS_HEATER_2
  4503. /**
  4504. * M128: Heater 2 valve open
  4505. */
  4506. inline void gcode_M128() { baricuda_e_to_p_pressure = code_seen('S') ? code_value_byte() : 255; }
  4507. /**
  4508. * M129: Heater 2 valve close
  4509. */
  4510. inline void gcode_M129() { baricuda_e_to_p_pressure = 0; }
  4511. #endif
  4512. #endif //BARICUDA
  4513. /**
  4514. * M140: Set bed temperature
  4515. */
  4516. inline void gcode_M140() {
  4517. if (DEBUGGING(DRYRUN)) return;
  4518. if (code_seen('S')) thermalManager.setTargetBed(code_value_temp_abs());
  4519. }
  4520. #if ENABLED(ULTIPANEL)
  4521. /**
  4522. * M145: Set the heatup state for a material in the LCD menu
  4523. * S<material> (0=PLA, 1=ABS)
  4524. * H<hotend temp>
  4525. * B<bed temp>
  4526. * F<fan speed>
  4527. */
  4528. inline void gcode_M145() {
  4529. int8_t material = code_seen('S') ? (int8_t)code_value_int() : 0;
  4530. if (material < 0 || material > 1) {
  4531. SERIAL_ERROR_START;
  4532. SERIAL_ERRORLNPGM(MSG_ERR_MATERIAL_INDEX);
  4533. }
  4534. else {
  4535. int v;
  4536. switch (material) {
  4537. case 0:
  4538. if (code_seen('H')) {
  4539. v = code_value_int();
  4540. preheatHotendTemp1 = constrain(v, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - 15);
  4541. }
  4542. if (code_seen('F')) {
  4543. v = code_value_int();
  4544. preheatFanSpeed1 = constrain(v, 0, 255);
  4545. }
  4546. #if TEMP_SENSOR_BED != 0
  4547. if (code_seen('B')) {
  4548. v = code_value_int();
  4549. preheatBedTemp1 = constrain(v, BED_MINTEMP, BED_MAXTEMP - 15);
  4550. }
  4551. #endif
  4552. break;
  4553. case 1:
  4554. if (code_seen('H')) {
  4555. v = code_value_int();
  4556. preheatHotendTemp2 = constrain(v, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - 15);
  4557. }
  4558. if (code_seen('F')) {
  4559. v = code_value_int();
  4560. preheatFanSpeed2 = constrain(v, 0, 255);
  4561. }
  4562. #if TEMP_SENSOR_BED != 0
  4563. if (code_seen('B')) {
  4564. v = code_value_int();
  4565. preheatBedTemp2 = constrain(v, BED_MINTEMP, BED_MAXTEMP - 15);
  4566. }
  4567. #endif
  4568. break;
  4569. }
  4570. }
  4571. }
  4572. #endif // ULTIPANEL
  4573. #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
  4574. /**
  4575. * M149: Set temperature units
  4576. */
  4577. inline void gcode_M149() {
  4578. if (code_seen('C')) {
  4579. set_input_temp_units(TEMPUNIT_C);
  4580. } else if (code_seen('K')) {
  4581. set_input_temp_units(TEMPUNIT_K);
  4582. } else if (code_seen('F')) {
  4583. set_input_temp_units(TEMPUNIT_F);
  4584. }
  4585. }
  4586. #endif
  4587. #if HAS_POWER_SWITCH
  4588. /**
  4589. * M80: Turn on Power Supply
  4590. */
  4591. inline void gcode_M80() {
  4592. OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); //GND
  4593. /**
  4594. * If you have a switch on suicide pin, this is useful
  4595. * if you want to start another print with suicide feature after
  4596. * a print without suicide...
  4597. */
  4598. #if HAS_SUICIDE
  4599. OUT_WRITE(SUICIDE_PIN, HIGH);
  4600. #endif
  4601. #if ENABLED(ULTIPANEL)
  4602. powersupply = true;
  4603. LCD_MESSAGEPGM(WELCOME_MSG);
  4604. lcd_update();
  4605. #endif
  4606. }
  4607. #endif // HAS_POWER_SWITCH
  4608. /**
  4609. * M81: Turn off Power, including Power Supply, if there is one.
  4610. *
  4611. * This code should ALWAYS be available for EMERGENCY SHUTDOWN!
  4612. */
  4613. inline void gcode_M81() {
  4614. thermalManager.disable_all_heaters();
  4615. stepper.finish_and_disable();
  4616. #if FAN_COUNT > 0
  4617. #if FAN_COUNT > 1
  4618. for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
  4619. #else
  4620. fanSpeeds[0] = 0;
  4621. #endif
  4622. #endif
  4623. delay(1000); // Wait 1 second before switching off
  4624. #if HAS_SUICIDE
  4625. stepper.synchronize();
  4626. suicide();
  4627. #elif HAS_POWER_SWITCH
  4628. OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP);
  4629. #endif
  4630. #if ENABLED(ULTIPANEL)
  4631. #if HAS_POWER_SWITCH
  4632. powersupply = false;
  4633. #endif
  4634. LCD_MESSAGEPGM(MACHINE_NAME " " MSG_OFF ".");
  4635. lcd_update();
  4636. #endif
  4637. }
  4638. /**
  4639. * M82: Set E codes absolute (default)
  4640. */
  4641. inline void gcode_M82() { axis_relative_modes[E_AXIS] = false; }
  4642. /**
  4643. * M83: Set E codes relative while in Absolute Coordinates (G90) mode
  4644. */
  4645. inline void gcode_M83() { axis_relative_modes[E_AXIS] = true; }
  4646. /**
  4647. * M18, M84: Disable all stepper motors
  4648. */
  4649. inline void gcode_M18_M84() {
  4650. if (code_seen('S')) {
  4651. stepper_inactive_time = code_value_millis_from_seconds();
  4652. }
  4653. else {
  4654. bool all_axis = !((code_seen('X')) || (code_seen('Y')) || (code_seen('Z')) || (code_seen('E')));
  4655. if (all_axis) {
  4656. stepper.finish_and_disable();
  4657. }
  4658. else {
  4659. stepper.synchronize();
  4660. if (code_seen('X')) disable_x();
  4661. if (code_seen('Y')) disable_y();
  4662. if (code_seen('Z')) disable_z();
  4663. #if ((E0_ENABLE_PIN != X_ENABLE_PIN) && (E1_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS
  4664. if (code_seen('E')) {
  4665. disable_e0();
  4666. disable_e1();
  4667. disable_e2();
  4668. disable_e3();
  4669. }
  4670. #endif
  4671. }
  4672. }
  4673. }
  4674. /**
  4675. * M85: Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
  4676. */
  4677. inline void gcode_M85() {
  4678. if (code_seen('S')) max_inactive_time = code_value_millis_from_seconds();
  4679. }
  4680. /**
  4681. * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E.
  4682. * (Follows the same syntax as G92)
  4683. */
  4684. inline void gcode_M92() {
  4685. LOOP_XYZE(i) {
  4686. if (code_seen(axis_codes[i])) {
  4687. if (i == E_AXIS) {
  4688. float value = code_value_per_axis_unit(i);
  4689. if (value < 20.0) {
  4690. float factor = planner.axis_steps_per_mm[i] / value; // increase e constants if M92 E14 is given for netfab.
  4691. planner.max_e_jerk *= factor;
  4692. planner.max_feedrate_mm_s[i] *= factor;
  4693. planner.max_acceleration_steps_per_s2[i] *= factor;
  4694. }
  4695. planner.axis_steps_per_mm[i] = value;
  4696. }
  4697. else {
  4698. planner.axis_steps_per_mm[i] = code_value_per_axis_unit(i);
  4699. }
  4700. }
  4701. }
  4702. planner.refresh_positioning();
  4703. }
  4704. /**
  4705. * Output the current position to serial
  4706. */
  4707. static void report_current_position() {
  4708. SERIAL_PROTOCOLPGM("X:");
  4709. SERIAL_PROTOCOL(current_position[X_AXIS]);
  4710. SERIAL_PROTOCOLPGM(" Y:");
  4711. SERIAL_PROTOCOL(current_position[Y_AXIS]);
  4712. SERIAL_PROTOCOLPGM(" Z:");
  4713. SERIAL_PROTOCOL(current_position[Z_AXIS]);
  4714. SERIAL_PROTOCOLPGM(" E:");
  4715. SERIAL_PROTOCOL(current_position[E_AXIS]);
  4716. stepper.report_positions();
  4717. #if IS_SCARA
  4718. SERIAL_PROTOCOLPAIR("SCARA Theta:", stepper.get_axis_position_degrees(A_AXIS));
  4719. SERIAL_PROTOCOLLNPAIR(" Psi+Theta:", stepper.get_axis_position_degrees(B_AXIS));
  4720. SERIAL_EOL;
  4721. #endif
  4722. }
  4723. /**
  4724. * M114: Output current position to serial port
  4725. */
  4726. inline void gcode_M114() { report_current_position(); }
  4727. /**
  4728. * M115: Capabilities string
  4729. */
  4730. inline void gcode_M115() {
  4731. SERIAL_PROTOCOLPGM(MSG_M115_REPORT);
  4732. }
  4733. /**
  4734. * M117: Set LCD Status Message
  4735. */
  4736. inline void gcode_M117() {
  4737. lcd_setstatus(current_command_args);
  4738. }
  4739. /**
  4740. * M119: Output endstop states to serial output
  4741. */
  4742. inline void gcode_M119() { endstops.M119(); }
  4743. /**
  4744. * M120: Enable endstops and set non-homing endstop state to "enabled"
  4745. */
  4746. inline void gcode_M120() { endstops.enable_globally(true); }
  4747. /**
  4748. * M121: Disable endstops and set non-homing endstop state to "disabled"
  4749. */
  4750. inline void gcode_M121() { endstops.enable_globally(false); }
  4751. #if ENABLED(BLINKM)
  4752. /**
  4753. * M150: Set Status LED Color - Use R-U-B for R-G-B
  4754. */
  4755. inline void gcode_M150() {
  4756. SendColors(
  4757. code_seen('R') ? code_value_byte() : 0,
  4758. code_seen('U') ? code_value_byte() : 0,
  4759. code_seen('B') ? code_value_byte() : 0
  4760. );
  4761. }
  4762. #endif // BLINKM
  4763. #if ENABLED(EXPERIMENTAL_I2CBUS)
  4764. /**
  4765. * M155: Send data to a I2C slave device
  4766. *
  4767. * This is a PoC, the formating and arguments for the GCODE will
  4768. * change to be more compatible, the current proposal is:
  4769. *
  4770. * M155 A<slave device address base 10> ; Sets the I2C slave address the data will be sent to
  4771. *
  4772. * M155 B<byte-1 value in base 10>
  4773. * M155 B<byte-2 value in base 10>
  4774. * M155 B<byte-3 value in base 10>
  4775. *
  4776. * M155 S1 ; Send the buffered data and reset the buffer
  4777. * M155 R1 ; Reset the buffer without sending data
  4778. *
  4779. */
  4780. inline void gcode_M155() {
  4781. // Set the target address
  4782. if (code_seen('A')) i2c.address(code_value_byte());
  4783. // Add a new byte to the buffer
  4784. if (code_seen('B')) i2c.addbyte(code_value_byte());
  4785. // Flush the buffer to the bus
  4786. if (code_seen('S')) i2c.send();
  4787. // Reset and rewind the buffer
  4788. else if (code_seen('R')) i2c.reset();
  4789. }
  4790. /**
  4791. * M156: Request X bytes from I2C slave device
  4792. *
  4793. * Usage: M156 A<slave device address base 10> B<number of bytes>
  4794. */
  4795. inline void gcode_M156() {
  4796. if (code_seen('A')) i2c.address(code_value_byte());
  4797. uint8_t bytes = code_seen('B') ? code_value_byte() : 1;
  4798. if (i2c.addr && bytes && bytes <= TWIBUS_BUFFER_SIZE) {
  4799. i2c.relay(bytes);
  4800. }
  4801. else {
  4802. SERIAL_ERROR_START;
  4803. SERIAL_ERRORLN("Bad i2c request");
  4804. }
  4805. }
  4806. #endif // EXPERIMENTAL_I2CBUS
  4807. /**
  4808. * M200: Set filament diameter and set E axis units to cubic units
  4809. *
  4810. * T<extruder> - Optional extruder number. Current extruder if omitted.
  4811. * D<linear> - Diameter of the filament. Use "D0" to switch back to linear units on the E axis.
  4812. */
  4813. inline void gcode_M200() {
  4814. if (get_target_extruder_from_command(200)) return;
  4815. if (code_seen('D')) {
  4816. // setting any extruder filament size disables volumetric on the assumption that
  4817. // slicers either generate in extruder values as cubic mm or as as filament feeds
  4818. // for all extruders
  4819. volumetric_enabled = (code_value_linear_units() != 0.0);
  4820. if (volumetric_enabled) {
  4821. filament_size[target_extruder] = code_value_linear_units();
  4822. // make sure all extruders have some sane value for the filament size
  4823. for (uint8_t i = 0; i < COUNT(filament_size); i++)
  4824. if (! filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
  4825. }
  4826. }
  4827. else {
  4828. //reserved for setting filament diameter via UFID or filament measuring device
  4829. return;
  4830. }
  4831. calculate_volumetric_multipliers();
  4832. }
  4833. /**
  4834. * M201: Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
  4835. */
  4836. inline void gcode_M201() {
  4837. LOOP_XYZE(i) {
  4838. if (code_seen(axis_codes[i])) {
  4839. planner.max_acceleration_mm_per_s2[i] = code_value_axis_units(i);
  4840. }
  4841. }
  4842. // steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)
  4843. planner.reset_acceleration_rates();
  4844. }
  4845. #if 0 // Not used for Sprinter/grbl gen6
  4846. inline void gcode_M202() {
  4847. LOOP_XYZE(i) {
  4848. if (code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value_axis_units(i) * planner.axis_steps_per_mm[i];
  4849. }
  4850. }
  4851. #endif
  4852. /**
  4853. * M203: Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in units/sec
  4854. */
  4855. inline void gcode_M203() {
  4856. LOOP_XYZE(i)
  4857. if (code_seen(axis_codes[i]))
  4858. planner.max_feedrate_mm_s[i] = code_value_axis_units(i);
  4859. }
  4860. /**
  4861. * M204: Set Accelerations in units/sec^2 (M204 P1200 R3000 T3000)
  4862. *
  4863. * P = Printing moves
  4864. * R = Retract only (no X, Y, Z) moves
  4865. * T = Travel (non printing) moves
  4866. *
  4867. * Also sets minimum segment time in ms (B20000) to prevent buffer under-runs and M20 minimum feedrate
  4868. */
  4869. inline void gcode_M204() {
  4870. if (code_seen('S')) { // Kept for legacy compatibility. Should NOT BE USED for new developments.
  4871. planner.travel_acceleration = planner.acceleration = code_value_linear_units();
  4872. SERIAL_ECHOLNPAIR("Setting Print and Travel Acceleration: ", planner.acceleration);
  4873. }
  4874. if (code_seen('P')) {
  4875. planner.acceleration = code_value_linear_units();
  4876. SERIAL_ECHOLNPAIR("Setting Print Acceleration: ", planner.acceleration);
  4877. }
  4878. if (code_seen('R')) {
  4879. planner.retract_acceleration = code_value_linear_units();
  4880. SERIAL_ECHOLNPAIR("Setting Retract Acceleration: ", planner.retract_acceleration);
  4881. }
  4882. if (code_seen('T')) {
  4883. planner.travel_acceleration = code_value_linear_units();
  4884. SERIAL_ECHOLNPAIR("Setting Travel Acceleration: ", planner.travel_acceleration);
  4885. }
  4886. }
  4887. /**
  4888. * M205: Set Advanced Settings
  4889. *
  4890. * S = Min Feed Rate (units/s)
  4891. * T = Min Travel Feed Rate (units/s)
  4892. * B = Min Segment Time (µs)
  4893. * X = Max XY Jerk (units/sec^2)
  4894. * Z = Max Z Jerk (units/sec^2)
  4895. * E = Max E Jerk (units/sec^2)
  4896. */
  4897. inline void gcode_M205() {
  4898. if (code_seen('S')) planner.min_feedrate_mm_s = code_value_linear_units();
  4899. if (code_seen('T')) planner.min_travel_feedrate_mm_s = code_value_linear_units();
  4900. if (code_seen('B')) planner.min_segment_time = code_value_millis();
  4901. if (code_seen('X')) planner.max_xy_jerk = code_value_linear_units();
  4902. if (code_seen('Z')) planner.max_z_jerk = code_value_axis_units(Z_AXIS);
  4903. if (code_seen('E')) planner.max_e_jerk = code_value_axis_units(E_AXIS);
  4904. }
  4905. /**
  4906. * M206: Set Additional Homing Offset (X Y Z). SCARA aliases T=X, P=Y
  4907. */
  4908. inline void gcode_M206() {
  4909. LOOP_XYZ(i)
  4910. if (code_seen(axis_codes[i]))
  4911. set_home_offset((AxisEnum)i, code_value_axis_units(i));
  4912. #if ENABLED(MORGAN_SCARA)
  4913. if (code_seen('T')) set_home_offset(A_AXIS, code_value_axis_units(A_AXIS)); // Theta
  4914. if (code_seen('P')) set_home_offset(B_AXIS, code_value_axis_units(B_AXIS)); // Psi
  4915. #endif
  4916. SYNC_PLAN_POSITION_KINEMATIC();
  4917. report_current_position();
  4918. }
  4919. #if ENABLED(DELTA)
  4920. /**
  4921. * M665: Set delta configurations
  4922. *
  4923. * L = diagonal rod
  4924. * R = delta radius
  4925. * S = segments per second
  4926. * A = Alpha (Tower 1) diagonal rod trim
  4927. * B = Beta (Tower 2) diagonal rod trim
  4928. * C = Gamma (Tower 3) diagonal rod trim
  4929. */
  4930. inline void gcode_M665() {
  4931. if (code_seen('L')) delta_diagonal_rod = code_value_linear_units();
  4932. if (code_seen('R')) delta_radius = code_value_linear_units();
  4933. if (code_seen('S')) delta_segments_per_second = code_value_float();
  4934. if (code_seen('A')) delta_diagonal_rod_trim_tower_1 = code_value_linear_units();
  4935. if (code_seen('B')) delta_diagonal_rod_trim_tower_2 = code_value_linear_units();
  4936. if (code_seen('C')) delta_diagonal_rod_trim_tower_3 = code_value_linear_units();
  4937. recalc_delta_settings(delta_radius, delta_diagonal_rod);
  4938. }
  4939. /**
  4940. * M666: Set delta endstop adjustment
  4941. */
  4942. inline void gcode_M666() {
  4943. #if ENABLED(DEBUG_LEVELING_FEATURE)
  4944. if (DEBUGGING(LEVELING)) {
  4945. SERIAL_ECHOLNPGM(">>> gcode_M666");
  4946. }
  4947. #endif
  4948. LOOP_XYZ(i) {
  4949. if (code_seen(axis_codes[i])) {
  4950. endstop_adj[i] = code_value_axis_units(i);
  4951. #if ENABLED(DEBUG_LEVELING_FEATURE)
  4952. if (DEBUGGING(LEVELING)) {
  4953. SERIAL_ECHOPAIR("endstop_adj[", axis_codes[i]);
  4954. SERIAL_ECHOLNPAIR("] = ", endstop_adj[i]);
  4955. }
  4956. #endif
  4957. }
  4958. }
  4959. #if ENABLED(DEBUG_LEVELING_FEATURE)
  4960. if (DEBUGGING(LEVELING)) {
  4961. SERIAL_ECHOLNPGM("<<< gcode_M666");
  4962. }
  4963. #endif
  4964. }
  4965. #elif ENABLED(Z_DUAL_ENDSTOPS) // !DELTA && ENABLED(Z_DUAL_ENDSTOPS)
  4966. /**
  4967. * M666: For Z Dual Endstop setup, set z axis offset to the z2 axis.
  4968. */
  4969. inline void gcode_M666() {
  4970. if (code_seen('Z')) z_endstop_adj = code_value_axis_units(Z_AXIS);
  4971. SERIAL_ECHOLNPAIR("Z Endstop Adjustment set to (mm):", z_endstop_adj);
  4972. }
  4973. #endif // !DELTA && Z_DUAL_ENDSTOPS
  4974. #if ENABLED(FWRETRACT)
  4975. /**
  4976. * M207: Set firmware retraction values
  4977. *
  4978. * S[+units] retract_length
  4979. * W[+units] retract_length_swap (multi-extruder)
  4980. * F[units/min] retract_feedrate_mm_s
  4981. * Z[units] retract_zlift
  4982. */
  4983. inline void gcode_M207() {
  4984. if (code_seen('S')) retract_length = code_value_axis_units(E_AXIS);
  4985. if (code_seen('F')) retract_feedrate_mm_s = MMM_TO_MMS(code_value_axis_units(E_AXIS));
  4986. if (code_seen('Z')) retract_zlift = code_value_axis_units(Z_AXIS);
  4987. #if EXTRUDERS > 1
  4988. if (code_seen('W')) retract_length_swap = code_value_axis_units(E_AXIS);
  4989. #endif
  4990. }
  4991. /**
  4992. * M208: Set firmware un-retraction values
  4993. *
  4994. * S[+units] retract_recover_length (in addition to M207 S*)
  4995. * W[+units] retract_recover_length_swap (multi-extruder)
  4996. * F[units/min] retract_recover_feedrate_mm_s
  4997. */
  4998. inline void gcode_M208() {
  4999. if (code_seen('S')) retract_recover_length = code_value_axis_units(E_AXIS);
  5000. if (code_seen('F')) retract_recover_feedrate_mm_s = MMM_TO_MMS(code_value_axis_units(E_AXIS));
  5001. #if EXTRUDERS > 1
  5002. if (code_seen('W')) retract_recover_length_swap = code_value_axis_units(E_AXIS);
  5003. #endif
  5004. }
  5005. /**
  5006. * M209: Enable automatic retract (M209 S1)
  5007. * detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.
  5008. */
  5009. inline void gcode_M209() {
  5010. if (code_seen('S')) {
  5011. autoretract_enabled = code_value_bool();
  5012. for (int i = 0; i < EXTRUDERS; i++) retracted[i] = false;
  5013. }
  5014. }
  5015. #endif // FWRETRACT
  5016. /**
  5017. * M211: Enable, Disable, and/or Report software endstops
  5018. *
  5019. * Usage: M211 S1 to enable, M211 S0 to disable, M211 alone for report
  5020. */
  5021. inline void gcode_M211() {
  5022. SERIAL_ECHO_START;
  5023. #if ENABLED(min_software_endstops) || ENABLED(max_software_endstops)
  5024. if (code_seen('S')) soft_endstops_enabled = code_value_bool();
  5025. #endif
  5026. #if ENABLED(min_software_endstops) || ENABLED(max_software_endstops)
  5027. SERIAL_ECHOPGM(MSG_SOFT_ENDSTOPS);
  5028. serialprintPGM(soft_endstops_enabled ? PSTR(MSG_ON) : PSTR(MSG_OFF));
  5029. #else
  5030. SERIAL_ECHOPGM(MSG_SOFT_ENDSTOPS);
  5031. SERIAL_ECHOPGM(MSG_OFF);
  5032. #endif
  5033. SERIAL_ECHOPGM(MSG_SOFT_MIN);
  5034. SERIAL_ECHOPAIR( MSG_X, soft_endstop_min[X_AXIS]);
  5035. SERIAL_ECHOPAIR(" " MSG_Y, soft_endstop_min[Y_AXIS]);
  5036. SERIAL_ECHOPAIR(" " MSG_Z, soft_endstop_min[Z_AXIS]);
  5037. SERIAL_ECHOPGM(MSG_SOFT_MAX);
  5038. SERIAL_ECHOPAIR( MSG_X, soft_endstop_max[X_AXIS]);
  5039. SERIAL_ECHOPAIR(" " MSG_Y, soft_endstop_max[Y_AXIS]);
  5040. SERIAL_ECHOLNPAIR(" " MSG_Z, soft_endstop_max[Z_AXIS]);
  5041. }
  5042. #if HOTENDS > 1
  5043. /**
  5044. * M218 - set hotend offset (in linear units)
  5045. *
  5046. * T<tool>
  5047. * X<xoffset>
  5048. * Y<yoffset>
  5049. * Z<zoffset> - Available with DUAL_X_CARRIAGE and SWITCHING_EXTRUDER
  5050. */
  5051. inline void gcode_M218() {
  5052. if (get_target_extruder_from_command(218)) return;
  5053. if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value_axis_units(X_AXIS);
  5054. if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value_axis_units(Y_AXIS);
  5055. #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
  5056. if (code_seen('Z')) hotend_offset[Z_AXIS][target_extruder] = code_value_axis_units(Z_AXIS);
  5057. #endif
  5058. SERIAL_ECHO_START;
  5059. SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
  5060. HOTEND_LOOP() {
  5061. SERIAL_CHAR(' ');
  5062. SERIAL_ECHO(hotend_offset[X_AXIS][e]);
  5063. SERIAL_CHAR(',');
  5064. SERIAL_ECHO(hotend_offset[Y_AXIS][e]);
  5065. #if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
  5066. SERIAL_CHAR(',');
  5067. SERIAL_ECHO(hotend_offset[Z_AXIS][e]);
  5068. #endif
  5069. }
  5070. SERIAL_EOL;
  5071. }
  5072. #endif // HOTENDS > 1
  5073. /**
  5074. * M220: Set speed percentage factor, aka "Feed Rate" (M220 S95)
  5075. */
  5076. inline void gcode_M220() {
  5077. if (code_seen('S')) feedrate_percentage = code_value_int();
  5078. }
  5079. /**
  5080. * M221: Set extrusion percentage (M221 T0 S95)
  5081. */
  5082. inline void gcode_M221() {
  5083. if (get_target_extruder_from_command(221)) return;
  5084. if (code_seen('S'))
  5085. flow_percentage[target_extruder] = code_value_int();
  5086. }
  5087. /**
  5088. * M226: Wait until the specified pin reaches the state required (M226 P<pin> S<state>)
  5089. */
  5090. inline void gcode_M226() {
  5091. if (code_seen('P')) {
  5092. int pin_number = code_value_int();
  5093. int pin_state = code_seen('S') ? code_value_int() : -1; // required pin state - default is inverted
  5094. if (pin_state >= -1 && pin_state <= 1) {
  5095. for (uint8_t i = 0; i < COUNT(sensitive_pins); i++) {
  5096. if (sensitive_pins[i] == pin_number) {
  5097. pin_number = -1;
  5098. break;
  5099. }
  5100. }
  5101. if (pin_number > -1) {
  5102. int target = LOW;
  5103. stepper.synchronize();
  5104. pinMode(pin_number, INPUT);
  5105. switch (pin_state) {
  5106. case 1:
  5107. target = HIGH;
  5108. break;
  5109. case 0:
  5110. target = LOW;
  5111. break;
  5112. case -1:
  5113. target = !digitalRead(pin_number);
  5114. break;
  5115. }
  5116. while (digitalRead(pin_number) != target) idle();
  5117. } // pin_number > -1
  5118. } // pin_state -1 0 1
  5119. } // code_seen('P')
  5120. }
  5121. #if HAS_SERVOS
  5122. /**
  5123. * M280: Get or set servo position. P<index> [S<angle>]
  5124. */
  5125. inline void gcode_M280() {
  5126. if (!code_seen('P')) return;
  5127. int servo_index = code_value_int();
  5128. if (servo_index >= 0 && servo_index < NUM_SERVOS) {
  5129. if (code_seen('S'))
  5130. MOVE_SERVO(servo_index, code_value_int());
  5131. else {
  5132. SERIAL_ECHO_START;
  5133. SERIAL_ECHOPAIR(" Servo ", servo_index);
  5134. SERIAL_ECHOLNPAIR(": ", servo[servo_index].read());
  5135. }
  5136. }
  5137. else {
  5138. SERIAL_ERROR_START;
  5139. SERIAL_ECHOPAIR("Servo ", servo_index);
  5140. SERIAL_ECHOLNPGM(" out of range");
  5141. }
  5142. }
  5143. #endif // HAS_SERVOS
  5144. #if HAS_BUZZER
  5145. /**
  5146. * M300: Play beep sound S<frequency Hz> P<duration ms>
  5147. */
  5148. inline void gcode_M300() {
  5149. uint16_t const frequency = code_seen('S') ? code_value_ushort() : 260;
  5150. uint16_t duration = code_seen('P') ? code_value_ushort() : 1000;
  5151. // Limits the tone duration to 0-5 seconds.
  5152. NOMORE(duration, 5000);
  5153. BUZZ(duration, frequency);
  5154. }
  5155. #endif // HAS_BUZZER
  5156. #if ENABLED(PIDTEMP)
  5157. /**
  5158. * M301: Set PID parameters P I D (and optionally C, L)
  5159. *
  5160. * P[float] Kp term
  5161. * I[float] Ki term (unscaled)
  5162. * D[float] Kd term (unscaled)
  5163. *
  5164. * With PID_EXTRUSION_SCALING:
  5165. *
  5166. * C[float] Kc term
  5167. * L[float] LPQ length
  5168. */
  5169. inline void gcode_M301() {
  5170. // multi-extruder PID patch: M301 updates or prints a single extruder's PID values
  5171. // default behaviour (omitting E parameter) is to update for extruder 0 only
  5172. int e = code_seen('E') ? code_value_int() : 0; // extruder being updated
  5173. if (e < HOTENDS) { // catch bad input value
  5174. if (code_seen('P')) PID_PARAM(Kp, e) = code_value_float();
  5175. if (code_seen('I')) PID_PARAM(Ki, e) = scalePID_i(code_value_float());
  5176. if (code_seen('D')) PID_PARAM(Kd, e) = scalePID_d(code_value_float());
  5177. #if ENABLED(PID_EXTRUSION_SCALING)
  5178. if (code_seen('C')) PID_PARAM(Kc, e) = code_value_float();
  5179. if (code_seen('L')) lpq_len = code_value_float();
  5180. NOMORE(lpq_len, LPQ_MAX_LEN);
  5181. #endif
  5182. thermalManager.updatePID();
  5183. SERIAL_ECHO_START;
  5184. #if ENABLED(PID_PARAMS_PER_HOTEND)
  5185. SERIAL_ECHOPAIR(" e:", e); // specify extruder in serial output
  5186. #endif // PID_PARAMS_PER_HOTEND
  5187. SERIAL_ECHOPAIR(" p:", PID_PARAM(Kp, e));
  5188. SERIAL_ECHOPAIR(" i:", unscalePID_i(PID_PARAM(Ki, e)));
  5189. SERIAL_ECHOPAIR(" d:", unscalePID_d(PID_PARAM(Kd, e)));
  5190. #if ENABLED(PID_EXTRUSION_SCALING)
  5191. //Kc does not have scaling applied above, or in resetting defaults
  5192. SERIAL_ECHOPAIR(" c:", PID_PARAM(Kc, e));
  5193. #endif
  5194. SERIAL_EOL;
  5195. }
  5196. else {
  5197. SERIAL_ERROR_START;
  5198. SERIAL_ERRORLN(MSG_INVALID_EXTRUDER);
  5199. }
  5200. }
  5201. #endif // PIDTEMP
  5202. #if ENABLED(PIDTEMPBED)
  5203. inline void gcode_M304() {
  5204. if (code_seen('P')) thermalManager.bedKp = code_value_float();
  5205. if (code_seen('I')) thermalManager.bedKi = scalePID_i(code_value_float());
  5206. if (code_seen('D')) thermalManager.bedKd = scalePID_d(code_value_float());
  5207. thermalManager.updatePID();
  5208. SERIAL_ECHO_START;
  5209. SERIAL_ECHOPAIR(" p:", thermalManager.bedKp);
  5210. SERIAL_ECHOPAIR(" i:", unscalePID_i(thermalManager.bedKi));
  5211. SERIAL_ECHOLNPAIR(" d:", unscalePID_d(thermalManager.bedKd));
  5212. }
  5213. #endif // PIDTEMPBED
  5214. #if defined(CHDK) || HAS_PHOTOGRAPH
  5215. /**
  5216. * M240: Trigger a camera by emulating a Canon RC-1
  5217. * See http://www.doc-diy.net/photo/rc-1_hacked/
  5218. */
  5219. inline void gcode_M240() {
  5220. #ifdef CHDK
  5221. OUT_WRITE(CHDK, HIGH);
  5222. chdkHigh = millis();
  5223. chdkActive = true;
  5224. #elif HAS_PHOTOGRAPH
  5225. const uint8_t NUM_PULSES = 16;
  5226. const float PULSE_LENGTH = 0.01524;
  5227. for (int i = 0; i < NUM_PULSES; i++) {
  5228. WRITE(PHOTOGRAPH_PIN, HIGH);
  5229. _delay_ms(PULSE_LENGTH);
  5230. WRITE(PHOTOGRAPH_PIN, LOW);
  5231. _delay_ms(PULSE_LENGTH);
  5232. }
  5233. delay(7.33);
  5234. for (int i = 0; i < NUM_PULSES; i++) {
  5235. WRITE(PHOTOGRAPH_PIN, HIGH);
  5236. _delay_ms(PULSE_LENGTH);
  5237. WRITE(PHOTOGRAPH_PIN, LOW);
  5238. _delay_ms(PULSE_LENGTH);
  5239. }
  5240. #endif // !CHDK && HAS_PHOTOGRAPH
  5241. }
  5242. #endif // CHDK || PHOTOGRAPH_PIN
  5243. #if HAS_LCD_CONTRAST
  5244. /**
  5245. * M250: Read and optionally set the LCD contrast
  5246. */
  5247. inline void gcode_M250() {
  5248. if (code_seen('C')) set_lcd_contrast(code_value_int());
  5249. SERIAL_PROTOCOLPGM("lcd contrast value: ");
  5250. SERIAL_PROTOCOL(lcd_contrast);
  5251. SERIAL_EOL;
  5252. }
  5253. #endif // HAS_LCD_CONTRAST
  5254. #if ENABLED(PREVENT_COLD_EXTRUSION)
  5255. /**
  5256. * M302: Allow cold extrudes, or set the minimum extrude temperature
  5257. *
  5258. * S<temperature> sets the minimum extrude temperature
  5259. * P<bool> enables (1) or disables (0) cold extrusion
  5260. *
  5261. * Examples:
  5262. *
  5263. * M302 ; report current cold extrusion state
  5264. * M302 P0 ; enable cold extrusion checking
  5265. * M302 P1 ; disables cold extrusion checking
  5266. * M302 S0 ; always allow extrusion (disables checking)
  5267. * M302 S170 ; only allow extrusion above 170
  5268. * M302 S170 P1 ; set min extrude temp to 170 but leave disabled
  5269. */
  5270. inline void gcode_M302() {
  5271. bool seen_S = code_seen('S');
  5272. if (seen_S) {
  5273. thermalManager.extrude_min_temp = code_value_temp_abs();
  5274. thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0);
  5275. }
  5276. if (code_seen('P'))
  5277. thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0) || code_value_bool();
  5278. else if (!seen_S) {
  5279. // Report current state
  5280. SERIAL_ECHO_START;
  5281. SERIAL_ECHOPAIR("Cold extrudes are ", (thermalManager.allow_cold_extrude ? "en" : "dis"));
  5282. SERIAL_ECHOPAIR("abled (min temp ", int(thermalManager.extrude_min_temp + 0.5));
  5283. SERIAL_ECHOLNPGM("C)");
  5284. }
  5285. }
  5286. #endif // PREVENT_COLD_EXTRUSION
  5287. /**
  5288. * M303: PID relay autotune
  5289. *
  5290. * S<temperature> sets the target temperature. (default 150C)
  5291. * E<extruder> (-1 for the bed) (default 0)
  5292. * C<cycles>
  5293. * U<bool> with a non-zero value will apply the result to current settings
  5294. */
  5295. inline void gcode_M303() {
  5296. #if HAS_PID_HEATING
  5297. int e = code_seen('E') ? code_value_int() : 0;
  5298. int c = code_seen('C') ? code_value_int() : 5;
  5299. bool u = code_seen('U') && code_value_bool();
  5300. float temp = code_seen('S') ? code_value_temp_abs() : (e < 0 ? 70.0 : 150.0);
  5301. if (e >= 0 && e < HOTENDS)
  5302. target_extruder = e;
  5303. KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
  5304. thermalManager.PID_autotune(temp, e, c, u);
  5305. KEEPALIVE_STATE(IN_HANDLER);
  5306. #else
  5307. SERIAL_ERROR_START;
  5308. SERIAL_ERRORLNPGM(MSG_ERR_M303_DISABLED);
  5309. #endif
  5310. }
  5311. #if ENABLED(MORGAN_SCARA)
  5312. bool SCARA_move_to_cal(uint8_t delta_a, uint8_t delta_b) {
  5313. if (IsRunning()) {
  5314. forward_kinematics_SCARA(delta_a, delta_b);
  5315. destination[X_AXIS] = LOGICAL_X_POSITION(cartes[X_AXIS]);
  5316. destination[Y_AXIS] = LOGICAL_Y_POSITION(cartes[Y_AXIS]);
  5317. destination[Z_AXIS] = current_position[Z_AXIS];
  5318. prepare_move_to_destination();
  5319. return true;
  5320. }
  5321. return false;
  5322. }
  5323. /**
  5324. * M360: SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
  5325. */
  5326. inline bool gcode_M360() {
  5327. SERIAL_ECHOLNPGM(" Cal: Theta 0");
  5328. return SCARA_move_to_cal(0, 120);
  5329. }
  5330. /**
  5331. * M361: SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
  5332. */
  5333. inline bool gcode_M361() {
  5334. SERIAL_ECHOLNPGM(" Cal: Theta 90");
  5335. return SCARA_move_to_cal(90, 130);
  5336. }
  5337. /**
  5338. * M362: SCARA calibration: Move to cal-position PsiA (0 deg calibration)
  5339. */
  5340. inline bool gcode_M362() {
  5341. SERIAL_ECHOLNPGM(" Cal: Psi 0");
  5342. return SCARA_move_to_cal(60, 180);
  5343. }
  5344. /**
  5345. * M363: SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
  5346. */
  5347. inline bool gcode_M363() {
  5348. SERIAL_ECHOLNPGM(" Cal: Psi 90");
  5349. return SCARA_move_to_cal(50, 90);
  5350. }
  5351. /**
  5352. * M364: SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
  5353. */
  5354. inline bool gcode_M364() {
  5355. SERIAL_ECHOLNPGM(" Cal: Theta-Psi 90");
  5356. return SCARA_move_to_cal(45, 135);
  5357. }
  5358. #endif // SCARA
  5359. #if ENABLED(EXT_SOLENOID)
  5360. void enable_solenoid(uint8_t num) {
  5361. switch (num) {
  5362. case 0:
  5363. OUT_WRITE(SOL0_PIN, HIGH);
  5364. break;
  5365. #if HAS_SOLENOID_1
  5366. case 1:
  5367. OUT_WRITE(SOL1_PIN, HIGH);
  5368. break;
  5369. #endif
  5370. #if HAS_SOLENOID_2
  5371. case 2:
  5372. OUT_WRITE(SOL2_PIN, HIGH);
  5373. break;
  5374. #endif
  5375. #if HAS_SOLENOID_3
  5376. case 3:
  5377. OUT_WRITE(SOL3_PIN, HIGH);
  5378. break;
  5379. #endif
  5380. default:
  5381. SERIAL_ECHO_START;
  5382. SERIAL_ECHOLNPGM(MSG_INVALID_SOLENOID);
  5383. break;
  5384. }
  5385. }
  5386. void enable_solenoid_on_active_extruder() { enable_solenoid(active_extruder); }
  5387. void disable_all_solenoids() {
  5388. OUT_WRITE(SOL0_PIN, LOW);
  5389. OUT_WRITE(SOL1_PIN, LOW);
  5390. OUT_WRITE(SOL2_PIN, LOW);
  5391. OUT_WRITE(SOL3_PIN, LOW);
  5392. }
  5393. /**
  5394. * M380: Enable solenoid on the active extruder
  5395. */
  5396. inline void gcode_M380() { enable_solenoid_on_active_extruder(); }
  5397. /**
  5398. * M381: Disable all solenoids
  5399. */
  5400. inline void gcode_M381() { disable_all_solenoids(); }
  5401. #endif // EXT_SOLENOID
  5402. /**
  5403. * M400: Finish all moves
  5404. */
  5405. inline void gcode_M400() { stepper.synchronize(); }
  5406. #if HAS_BED_PROBE
  5407. /**
  5408. * M401: Engage Z Servo endstop if available
  5409. */
  5410. inline void gcode_M401() { DEPLOY_PROBE(); }
  5411. /**
  5412. * M402: Retract Z Servo endstop if enabled
  5413. */
  5414. inline void gcode_M402() { STOW_PROBE(); }
  5415. #endif // HAS_BED_PROBE
  5416. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  5417. /**
  5418. * M404: Display or set (in current units) the nominal filament width (3mm, 1.75mm ) W<3.0>
  5419. */
  5420. inline void gcode_M404() {
  5421. if (code_seen('W')) {
  5422. filament_width_nominal = code_value_linear_units();
  5423. }
  5424. else {
  5425. SERIAL_PROTOCOLPGM("Filament dia (nominal mm):");
  5426. SERIAL_PROTOCOLLN(filament_width_nominal);
  5427. }
  5428. }
  5429. /**
  5430. * M405: Turn on filament sensor for control
  5431. */
  5432. inline void gcode_M405() {
  5433. // This is technically a linear measurement, but since it's quantized to centimeters and is a different unit than
  5434. // everything else, it uses code_value_int() instead of code_value_linear_units().
  5435. if (code_seen('D')) meas_delay_cm = code_value_int();
  5436. NOMORE(meas_delay_cm, MAX_MEASUREMENT_DELAY);
  5437. if (filwidth_delay_index[1] == -1) { // Initialize the ring buffer if not done since startup
  5438. int temp_ratio = thermalManager.widthFil_to_size_ratio();
  5439. for (uint8_t i = 0; i < COUNT(measurement_delay); ++i)
  5440. measurement_delay[i] = temp_ratio - 100; // Subtract 100 to scale within a signed byte
  5441. filwidth_delay_index[0] = filwidth_delay_index[1] = 0;
  5442. }
  5443. filament_sensor = true;
  5444. //SERIAL_PROTOCOLPGM("Filament dia (measured mm):");
  5445. //SERIAL_PROTOCOL(filament_width_meas);
  5446. //SERIAL_PROTOCOLPGM("Extrusion ratio(%):");
  5447. //SERIAL_PROTOCOL(flow_percentage[active_extruder]);
  5448. }
  5449. /**
  5450. * M406: Turn off filament sensor for control
  5451. */
  5452. inline void gcode_M406() { filament_sensor = false; }
  5453. /**
  5454. * M407: Get measured filament diameter on serial output
  5455. */
  5456. inline void gcode_M407() {
  5457. SERIAL_PROTOCOLPGM("Filament dia (measured mm):");
  5458. SERIAL_PROTOCOLLN(filament_width_meas);
  5459. }
  5460. #endif // FILAMENT_WIDTH_SENSOR
  5461. void quickstop_stepper() {
  5462. stepper.quick_stop();
  5463. stepper.synchronize();
  5464. set_current_from_steppers_for_axis(ALL_AXES);
  5465. SYNC_PLAN_POSITION_KINEMATIC();
  5466. }
  5467. #if PLANNER_LEVELING
  5468. /**
  5469. * M420: Enable/Disable Bed Leveling
  5470. */
  5471. inline void gcode_M420() { if (code_seen('S')) set_bed_leveling_enabled(code_value_bool()); }
  5472. #endif
  5473. #if ENABLED(MESH_BED_LEVELING)
  5474. /**
  5475. * M421: Set a single Mesh Bed Leveling Z coordinate
  5476. * Use either 'M421 X<linear> Y<linear> Z<linear>' or 'M421 I<xindex> J<yindex> Z<linear>'
  5477. */
  5478. inline void gcode_M421() {
  5479. int8_t px = 0, py = 0;
  5480. float z = 0;
  5481. bool hasX, hasY, hasZ, hasI, hasJ;
  5482. if ((hasX = code_seen('X'))) px = mbl.probe_index_x(code_value_axis_units(X_AXIS));
  5483. if ((hasY = code_seen('Y'))) py = mbl.probe_index_y(code_value_axis_units(Y_AXIS));
  5484. if ((hasI = code_seen('I'))) px = code_value_axis_units(X_AXIS);
  5485. if ((hasJ = code_seen('J'))) py = code_value_axis_units(Y_AXIS);
  5486. if ((hasZ = code_seen('Z'))) z = code_value_axis_units(Z_AXIS);
  5487. if (hasX && hasY && hasZ) {
  5488. if (px >= 0 && py >= 0)
  5489. mbl.set_z(px, py, z);
  5490. else {
  5491. SERIAL_ERROR_START;
  5492. SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
  5493. }
  5494. }
  5495. else if (hasI && hasJ && hasZ) {
  5496. if (px >= 0 && px < MESH_NUM_X_POINTS && py >= 0 && py < MESH_NUM_Y_POINTS)
  5497. mbl.set_z(px, py, z);
  5498. else {
  5499. SERIAL_ERROR_START;
  5500. SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
  5501. }
  5502. }
  5503. else {
  5504. SERIAL_ERROR_START;
  5505. SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
  5506. }
  5507. }
  5508. #endif
  5509. /**
  5510. * M428: Set home_offset based on the distance between the
  5511. * current_position and the nearest "reference point."
  5512. * If an axis is past center its endstop position
  5513. * is the reference-point. Otherwise it uses 0. This allows
  5514. * the Z offset to be set near the bed when using a max endstop.
  5515. *
  5516. * M428 can't be used more than 2cm away from 0 or an endstop.
  5517. *
  5518. * Use M206 to set these values directly.
  5519. */
  5520. inline void gcode_M428() {
  5521. bool err = false;
  5522. LOOP_XYZ(i) {
  5523. if (axis_homed[i]) {
  5524. float base = (current_position[i] > (soft_endstop_min[i] + soft_endstop_max[i]) * 0.5) ? base_home_pos(i) : 0,
  5525. diff = current_position[i] - LOGICAL_POSITION(base, i);
  5526. if (diff > -20 && diff < 20) {
  5527. set_home_offset((AxisEnum)i, home_offset[i] - diff);
  5528. }
  5529. else {
  5530. SERIAL_ERROR_START;
  5531. SERIAL_ERRORLNPGM(MSG_ERR_M428_TOO_FAR);
  5532. LCD_ALERTMESSAGEPGM("Err: Too far!");
  5533. BUZZ(200, 40);
  5534. err = true;
  5535. break;
  5536. }
  5537. }
  5538. }
  5539. if (!err) {
  5540. SYNC_PLAN_POSITION_KINEMATIC();
  5541. report_current_position();
  5542. LCD_MESSAGEPGM(MSG_HOME_OFFSETS_APPLIED);
  5543. BUZZ(200, 659);
  5544. BUZZ(200, 698);
  5545. }
  5546. }
  5547. /**
  5548. * M500: Store settings in EEPROM
  5549. */
  5550. inline void gcode_M500() {
  5551. Config_StoreSettings();
  5552. }
  5553. /**
  5554. * M501: Read settings from EEPROM
  5555. */
  5556. inline void gcode_M501() {
  5557. Config_RetrieveSettings();
  5558. }
  5559. /**
  5560. * M502: Revert to default settings
  5561. */
  5562. inline void gcode_M502() {
  5563. Config_ResetDefault();
  5564. }
  5565. /**
  5566. * M503: print settings currently in memory
  5567. */
  5568. inline void gcode_M503() {
  5569. Config_PrintSettings(code_seen('S') && !code_value_bool());
  5570. }
  5571. #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
  5572. /**
  5573. * M540: Set whether SD card print should abort on endstop hit (M540 S<0|1>)
  5574. */
  5575. inline void gcode_M540() {
  5576. if (code_seen('S')) stepper.abort_on_endstop_hit = code_value_bool();
  5577. }
  5578. #endif // ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
  5579. #if HAS_BED_PROBE
  5580. inline void gcode_M851() {
  5581. SERIAL_ECHO_START;
  5582. SERIAL_ECHOPGM(MSG_ZPROBE_ZOFFSET);
  5583. SERIAL_CHAR(' ');
  5584. if (code_seen('Z')) {
  5585. float value = code_value_axis_units(Z_AXIS);
  5586. if (Z_PROBE_OFFSET_RANGE_MIN <= value && value <= Z_PROBE_OFFSET_RANGE_MAX) {
  5587. zprobe_zoffset = value;
  5588. SERIAL_ECHO(zprobe_zoffset);
  5589. }
  5590. else {
  5591. SERIAL_ECHOPAIR(MSG_Z_MIN, Z_PROBE_OFFSET_RANGE_MIN);
  5592. SERIAL_CHAR(' ');
  5593. SERIAL_ECHOPAIR(MSG_Z_MAX, Z_PROBE_OFFSET_RANGE_MAX);
  5594. }
  5595. }
  5596. else {
  5597. SERIAL_ECHOPAIR(": ", zprobe_zoffset);
  5598. }
  5599. SERIAL_EOL;
  5600. }
  5601. #endif // HAS_BED_PROBE
  5602. #if ENABLED(FILAMENT_CHANGE_FEATURE)
  5603. /**
  5604. * M600: Pause for filament change
  5605. *
  5606. * E[distance] - Retract the filament this far (negative value)
  5607. * Z[distance] - Move the Z axis by this distance
  5608. * X[position] - Move to this X position, with Y
  5609. * Y[position] - Move to this Y position, with X
  5610. * L[distance] - Retract distance for removal (manual reload)
  5611. *
  5612. * Default values are used for omitted arguments.
  5613. *
  5614. */
  5615. inline void gcode_M600() {
  5616. if (thermalManager.tooColdToExtrude(active_extruder)) {
  5617. SERIAL_ERROR_START;
  5618. SERIAL_ERRORLNPGM(MSG_TOO_COLD_FOR_M600);
  5619. return;
  5620. }
  5621. // Show initial message and wait for synchronize steppers
  5622. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_INIT);
  5623. stepper.synchronize();
  5624. float lastpos[NUM_AXIS];
  5625. // Save current position of all axes
  5626. LOOP_XYZE(i)
  5627. lastpos[i] = destination[i] = current_position[i];
  5628. // Define runplan for move axes
  5629. #if IS_KINEMATIC
  5630. #define RUNPLAN(RATE_MM_S) inverse_kinematics(destination); \
  5631. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], RATE_MM_S, active_extruder);
  5632. #else
  5633. #define RUNPLAN(RATE_MM_S) line_to_destination(RATE_MM_S);
  5634. #endif
  5635. KEEPALIVE_STATE(IN_HANDLER);
  5636. // Initial retract before move to filament change position
  5637. if (code_seen('E')) destination[E_AXIS] += code_value_axis_units(E_AXIS);
  5638. #if defined(FILAMENT_CHANGE_RETRACT_LENGTH) && FILAMENT_CHANGE_RETRACT_LENGTH > 0
  5639. else destination[E_AXIS] -= FILAMENT_CHANGE_RETRACT_LENGTH;
  5640. #endif
  5641. RUNPLAN(FILAMENT_CHANGE_RETRACT_FEEDRATE);
  5642. // Lift Z axis
  5643. float z_lift = code_seen('Z') ? code_value_axis_units(Z_AXIS) :
  5644. #if defined(FILAMENT_CHANGE_Z_ADD) && FILAMENT_CHANGE_Z_ADD > 0
  5645. FILAMENT_CHANGE_Z_ADD
  5646. #else
  5647. 0
  5648. #endif
  5649. ;
  5650. if (z_lift > 0) {
  5651. destination[Z_AXIS] += z_lift;
  5652. NOMORE(destination[Z_AXIS], Z_MAX_POS);
  5653. RUNPLAN(FILAMENT_CHANGE_Z_FEEDRATE);
  5654. }
  5655. // Move XY axes to filament exchange position
  5656. if (code_seen('X')) destination[X_AXIS] = code_value_axis_units(X_AXIS);
  5657. #ifdef FILAMENT_CHANGE_X_POS
  5658. else destination[X_AXIS] = FILAMENT_CHANGE_X_POS;
  5659. #endif
  5660. if (code_seen('Y')) destination[Y_AXIS] = code_value_axis_units(Y_AXIS);
  5661. #ifdef FILAMENT_CHANGE_Y_POS
  5662. else destination[Y_AXIS] = FILAMENT_CHANGE_Y_POS;
  5663. #endif
  5664. RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE);
  5665. stepper.synchronize();
  5666. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_UNLOAD);
  5667. // Unload filament
  5668. if (code_seen('L')) destination[E_AXIS] += code_value_axis_units(E_AXIS);
  5669. #if defined(FILAMENT_CHANGE_UNLOAD_LENGTH) && FILAMENT_CHANGE_UNLOAD_LENGTH > 0
  5670. else destination[E_AXIS] -= FILAMENT_CHANGE_UNLOAD_LENGTH;
  5671. #endif
  5672. RUNPLAN(FILAMENT_CHANGE_UNLOAD_FEEDRATE);
  5673. // Synchronize steppers and then disable extruders steppers for manual filament changing
  5674. stepper.synchronize();
  5675. disable_e0();
  5676. disable_e1();
  5677. disable_e2();
  5678. disable_e3();
  5679. delay(100);
  5680. #if HAS_BUZZER
  5681. millis_t next_tick = 0;
  5682. #endif
  5683. // Wait for filament insert by user and press button
  5684. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_INSERT);
  5685. while (!lcd_clicked()) {
  5686. #if HAS_BUZZER
  5687. millis_t ms = millis();
  5688. if (ms >= next_tick) {
  5689. BUZZ(300, 2000);
  5690. next_tick = ms + 2500; // Beep every 2.5s while waiting
  5691. }
  5692. #endif
  5693. idle(true);
  5694. }
  5695. delay(100);
  5696. while (lcd_clicked()) idle(true);
  5697. delay(100);
  5698. // Show load message
  5699. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_LOAD);
  5700. // Load filament
  5701. if (code_seen('L')) destination[E_AXIS] -= code_value_axis_units(E_AXIS);
  5702. #if defined(FILAMENT_CHANGE_LOAD_LENGTH) && FILAMENT_CHANGE_LOAD_LENGTH > 0
  5703. else destination[E_AXIS] += FILAMENT_CHANGE_LOAD_LENGTH;
  5704. #endif
  5705. RUNPLAN(FILAMENT_CHANGE_LOAD_FEEDRATE);
  5706. stepper.synchronize();
  5707. #if defined(FILAMENT_CHANGE_EXTRUDE_LENGTH) && FILAMENT_CHANGE_EXTRUDE_LENGTH > 0
  5708. do {
  5709. // Extrude filament to get into hotend
  5710. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_EXTRUDE);
  5711. destination[E_AXIS] += FILAMENT_CHANGE_EXTRUDE_LENGTH;
  5712. RUNPLAN(FILAMENT_CHANGE_EXTRUDE_FEEDRATE);
  5713. stepper.synchronize();
  5714. // Ask user if more filament should be extruded
  5715. KEEPALIVE_STATE(PAUSED_FOR_USER);
  5716. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_OPTION);
  5717. while (filament_change_menu_response == FILAMENT_CHANGE_RESPONSE_WAIT_FOR) idle(true);
  5718. KEEPALIVE_STATE(IN_HANDLER);
  5719. } while (filament_change_menu_response != FILAMENT_CHANGE_RESPONSE_RESUME_PRINT);
  5720. #endif
  5721. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_RESUME);
  5722. KEEPALIVE_STATE(IN_HANDLER);
  5723. // Set extruder to saved position
  5724. current_position[E_AXIS] = lastpos[E_AXIS];
  5725. destination[E_AXIS] = lastpos[E_AXIS];
  5726. planner.set_e_position_mm(current_position[E_AXIS]);
  5727. #if IS_KINEMATIC
  5728. // Move XYZ to starting position, then E
  5729. inverse_kinematics(lastpos);
  5730. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], destination[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
  5731. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], lastpos[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder);
  5732. #else
  5733. // Move XY to starting position, then Z, then E
  5734. destination[X_AXIS] = lastpos[X_AXIS];
  5735. destination[Y_AXIS] = lastpos[Y_AXIS];
  5736. RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE);
  5737. destination[Z_AXIS] = lastpos[Z_AXIS];
  5738. RUNPLAN(FILAMENT_CHANGE_Z_FEEDRATE);
  5739. #endif
  5740. stepper.synchronize();
  5741. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  5742. filament_ran_out = false;
  5743. #endif
  5744. // Show status screen
  5745. lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_STATUS);
  5746. }
  5747. #endif // FILAMENT_CHANGE_FEATURE
  5748. #if ENABLED(DUAL_X_CARRIAGE)
  5749. /**
  5750. * M605: Set dual x-carriage movement mode
  5751. *
  5752. * M605 S0: Full control mode. The slicer has full control over x-carriage movement
  5753. * M605 S1: Auto-park mode. The inactive head will auto park/unpark without slicer involvement
  5754. * M605 S2 [Xnnn] [Rmmm]: Duplication mode. The second extruder will duplicate the first with nnn
  5755. * units x-offset and an optional differential hotend temperature of
  5756. * mmm degrees. E.g., with "M605 S2 X100 R2" the second extruder will duplicate
  5757. * the first with a spacing of 100mm in the x direction and 2 degrees hotter.
  5758. *
  5759. * Note: the X axis should be homed after changing dual x-carriage mode.
  5760. */
  5761. inline void gcode_M605() {
  5762. stepper.synchronize();
  5763. if (code_seen('S')) dual_x_carriage_mode = code_value_byte();
  5764. switch (dual_x_carriage_mode) {
  5765. case DXC_DUPLICATION_MODE:
  5766. if (code_seen('X')) duplicate_extruder_x_offset = max(code_value_axis_units(X_AXIS), X2_MIN_POS - x_home_pos(0));
  5767. if (code_seen('R')) duplicate_extruder_temp_offset = code_value_temp_diff();
  5768. SERIAL_ECHO_START;
  5769. SERIAL_ECHOPGM(MSG_HOTEND_OFFSET);
  5770. SERIAL_CHAR(' ');
  5771. SERIAL_ECHO(hotend_offset[X_AXIS][0]);
  5772. SERIAL_CHAR(',');
  5773. SERIAL_ECHO(hotend_offset[Y_AXIS][0]);
  5774. SERIAL_CHAR(' ');
  5775. SERIAL_ECHO(duplicate_extruder_x_offset);
  5776. SERIAL_CHAR(',');
  5777. SERIAL_ECHOLN(hotend_offset[Y_AXIS][1]);
  5778. break;
  5779. case DXC_FULL_CONTROL_MODE:
  5780. case DXC_AUTO_PARK_MODE:
  5781. break;
  5782. default:
  5783. dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
  5784. break;
  5785. }
  5786. active_extruder_parked = false;
  5787. extruder_duplication_enabled = false;
  5788. delayed_move_time = 0;
  5789. }
  5790. #elif ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
  5791. inline void gcode_M605() {
  5792. stepper.synchronize();
  5793. extruder_duplication_enabled = code_seen('S') && code_value_int() == 2;
  5794. SERIAL_ECHO_START;
  5795. SERIAL_ECHOLNPAIR(MSG_DUPLICATION_MODE, extruder_duplication_enabled ? MSG_ON : MSG_OFF);
  5796. }
  5797. #endif // M605
  5798. #if ENABLED(LIN_ADVANCE)
  5799. /**
  5800. * M905: Set advance factor
  5801. */
  5802. inline void gcode_M905() {
  5803. stepper.synchronize();
  5804. stepper.advance_M905(code_seen('K') ? code_value_float() : -1.0);
  5805. }
  5806. #endif
  5807. /**
  5808. * M907: Set digital trimpot motor current using axis codes X, Y, Z, E, B, S
  5809. */
  5810. inline void gcode_M907() {
  5811. #if HAS_DIGIPOTSS
  5812. LOOP_XYZE(i)
  5813. if (code_seen(axis_codes[i])) stepper.digipot_current(i, code_value_int());
  5814. if (code_seen('B')) stepper.digipot_current(4, code_value_int());
  5815. if (code_seen('S')) for (int i = 0; i <= 4; i++) stepper.digipot_current(i, code_value_int());
  5816. #elif HAS_MOTOR_CURRENT_PWM
  5817. #if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
  5818. if (code_seen('X')) stepper.digipot_current(0, code_value_int());
  5819. #endif
  5820. #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
  5821. if (code_seen('Z')) stepper.digipot_current(1, code_value_int());
  5822. #endif
  5823. #if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
  5824. if (code_seen('E')) stepper.digipot_current(2, code_value_int());
  5825. #endif
  5826. #endif
  5827. #if ENABLED(DIGIPOT_I2C)
  5828. // this one uses actual amps in floating point
  5829. LOOP_XYZE(i) if (code_seen(axis_codes[i])) digipot_i2c_set_current(i, code_value_float());
  5830. // for each additional extruder (named B,C,D,E..., channels 4,5,6,7...)
  5831. for (int i = NUM_AXIS; i < DIGIPOT_I2C_NUM_CHANNELS; i++) if (code_seen('B' + i - (NUM_AXIS))) digipot_i2c_set_current(i, code_value_float());
  5832. #endif
  5833. #if ENABLED(DAC_STEPPER_CURRENT)
  5834. if (code_seen('S')) {
  5835. float dac_percent = code_value_float();
  5836. for (uint8_t i = 0; i <= 4; i++) dac_current_percent(i, dac_percent);
  5837. }
  5838. LOOP_XYZE(i) if (code_seen(axis_codes[i])) dac_current_percent(i, code_value_float());
  5839. #endif
  5840. }
  5841. #if HAS_DIGIPOTSS || ENABLED(DAC_STEPPER_CURRENT)
  5842. /**
  5843. * M908: Control digital trimpot directly (M908 P<pin> S<current>)
  5844. */
  5845. inline void gcode_M908() {
  5846. #if HAS_DIGIPOTSS
  5847. stepper.digitalPotWrite(
  5848. code_seen('P') ? code_value_int() : 0,
  5849. code_seen('S') ? code_value_int() : 0
  5850. );
  5851. #endif
  5852. #ifdef DAC_STEPPER_CURRENT
  5853. dac_current_raw(
  5854. code_seen('P') ? code_value_byte() : -1,
  5855. code_seen('S') ? code_value_ushort() : 0
  5856. );
  5857. #endif
  5858. }
  5859. #if ENABLED(DAC_STEPPER_CURRENT) // As with Printrbot RevF
  5860. inline void gcode_M909() { dac_print_values(); }
  5861. inline void gcode_M910() { dac_commit_eeprom(); }
  5862. #endif
  5863. #endif // HAS_DIGIPOTSS || DAC_STEPPER_CURRENT
  5864. #if HAS_MICROSTEPS
  5865. // M350 Set microstepping mode. Warning: Steps per unit remains unchanged. S code sets stepping mode for all drivers.
  5866. inline void gcode_M350() {
  5867. if (code_seen('S')) for (int i = 0; i <= 4; i++) stepper.microstep_mode(i, code_value_byte());
  5868. LOOP_XYZE(i) if (code_seen(axis_codes[i])) stepper.microstep_mode(i, code_value_byte());
  5869. if (code_seen('B')) stepper.microstep_mode(4, code_value_byte());
  5870. stepper.microstep_readings();
  5871. }
  5872. /**
  5873. * M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B
  5874. * S# determines MS1 or MS2, X# sets the pin high/low.
  5875. */
  5876. inline void gcode_M351() {
  5877. if (code_seen('S')) switch (code_value_byte()) {
  5878. case 1:
  5879. LOOP_XYZE(i) if (code_seen(axis_codes[i])) stepper.microstep_ms(i, code_value_byte(), -1);
  5880. if (code_seen('B')) stepper.microstep_ms(4, code_value_byte(), -1);
  5881. break;
  5882. case 2:
  5883. LOOP_XYZE(i) if (code_seen(axis_codes[i])) stepper.microstep_ms(i, -1, code_value_byte());
  5884. if (code_seen('B')) stepper.microstep_ms(4, -1, code_value_byte());
  5885. break;
  5886. }
  5887. stepper.microstep_readings();
  5888. }
  5889. #endif // HAS_MICROSTEPS
  5890. #if ENABLED(MIXING_EXTRUDER)
  5891. /**
  5892. * M163: Set a single mix factor for a mixing extruder
  5893. * This is called "weight" by some systems.
  5894. *
  5895. * S[index] The channel index to set
  5896. * P[float] The mix value
  5897. *
  5898. */
  5899. inline void gcode_M163() {
  5900. int mix_index = code_seen('S') ? code_value_int() : 0;
  5901. float mix_value = code_seen('P') ? code_value_float() : 0.0;
  5902. if (mix_index < MIXING_STEPPERS) mixing_factor[mix_index] = mix_value;
  5903. }
  5904. #if MIXING_VIRTUAL_TOOLS > 1
  5905. /**
  5906. * M164: Store the current mix factors as a virtual tool.
  5907. *
  5908. * S[index] The virtual tool to store
  5909. *
  5910. */
  5911. inline void gcode_M164() {
  5912. int tool_index = code_seen('S') ? code_value_int() : 0;
  5913. if (tool_index < MIXING_VIRTUAL_TOOLS) {
  5914. normalize_mix();
  5915. for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
  5916. mixing_virtual_tool_mix[tool_index][i] = mixing_factor[i];
  5917. }
  5918. }
  5919. #endif
  5920. #if ENABLED(DIRECT_MIXING_IN_G1)
  5921. /**
  5922. * M165: Set multiple mix factors for a mixing extruder.
  5923. * Factors that are left out will be set to 0.
  5924. * All factors together must add up to 1.0.
  5925. *
  5926. * A[factor] Mix factor for extruder stepper 1
  5927. * B[factor] Mix factor for extruder stepper 2
  5928. * C[factor] Mix factor for extruder stepper 3
  5929. * D[factor] Mix factor for extruder stepper 4
  5930. * H[factor] Mix factor for extruder stepper 5
  5931. * I[factor] Mix factor for extruder stepper 6
  5932. *
  5933. */
  5934. inline void gcode_M165() { gcode_get_mix(); }
  5935. #endif
  5936. #endif // MIXING_EXTRUDER
  5937. /**
  5938. * M999: Restart after being stopped
  5939. *
  5940. * Default behaviour is to flush the serial buffer and request
  5941. * a resend to the host starting on the last N line received.
  5942. *
  5943. * Sending "M999 S1" will resume printing without flushing the
  5944. * existing command buffer.
  5945. *
  5946. */
  5947. inline void gcode_M999() {
  5948. Running = true;
  5949. lcd_reset_alert_level();
  5950. if (code_seen('S') && code_value_bool()) return;
  5951. // gcode_LastN = Stopped_gcode_LastN;
  5952. FlushSerialRequestResend();
  5953. }
  5954. #if ENABLED(SWITCHING_EXTRUDER)
  5955. inline void move_extruder_servo(uint8_t e) {
  5956. const int angles[2] = SWITCHING_EXTRUDER_SERVO_ANGLES;
  5957. MOVE_SERVO(SWITCHING_EXTRUDER_SERVO_NR, angles[e]);
  5958. }
  5959. #endif
  5960. inline void invalid_extruder_error(const uint8_t &e) {
  5961. SERIAL_ECHO_START;
  5962. SERIAL_CHAR('T');
  5963. SERIAL_PROTOCOL_F(e, DEC);
  5964. SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
  5965. }
  5966. /**
  5967. * Perform a tool-change, which may result in moving the
  5968. * previous tool out of the way and the new tool into place.
  5969. */
  5970. void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) {
  5971. #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
  5972. if (tmp_extruder >= MIXING_VIRTUAL_TOOLS) {
  5973. invalid_extruder_error(tmp_extruder);
  5974. return;
  5975. }
  5976. // T0-Tnnn: Switch virtual tool by changing the mix
  5977. for (uint8_t j = 0; j < MIXING_STEPPERS; j++)
  5978. mixing_factor[j] = mixing_virtual_tool_mix[tmp_extruder][j];
  5979. #else //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
  5980. #if HOTENDS > 1
  5981. if (tmp_extruder >= EXTRUDERS) {
  5982. invalid_extruder_error(tmp_extruder);
  5983. return;
  5984. }
  5985. float old_feedrate_mm_s = feedrate_mm_s;
  5986. feedrate_mm_s = fr_mm_s > 0.0 ? (old_feedrate_mm_s = fr_mm_s) : XY_PROBE_FEEDRATE_MM_S;
  5987. if (tmp_extruder != active_extruder) {
  5988. if (!no_move && axis_unhomed_error(true, true, true)) {
  5989. SERIAL_ECHOLNPGM("No move on toolchange");
  5990. no_move = true;
  5991. }
  5992. // Save current position to destination, for use later
  5993. set_destination_to_current();
  5994. #if ENABLED(DUAL_X_CARRIAGE)
  5995. #if ENABLED(DEBUG_LEVELING_FEATURE)
  5996. if (DEBUGGING(LEVELING)) {
  5997. SERIAL_ECHOPGM("Dual X Carriage Mode ");
  5998. switch (dual_x_carriage_mode) {
  5999. case DXC_DUPLICATION_MODE: SERIAL_ECHOLNPGM("DXC_DUPLICATION_MODE"); break;
  6000. case DXC_AUTO_PARK_MODE: SERIAL_ECHOLNPGM("DXC_AUTO_PARK_MODE"); break;
  6001. case DXC_FULL_CONTROL_MODE: SERIAL_ECHOLNPGM("DXC_FULL_CONTROL_MODE"); break;
  6002. }
  6003. }
  6004. #endif
  6005. if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() &&
  6006. (delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder))
  6007. ) {
  6008. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6009. if (DEBUGGING(LEVELING)) {
  6010. SERIAL_ECHOPAIR("Raise to ", current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT); SERIAL_EOL;
  6011. SERIAL_ECHOPAIR("MoveX to ", x_home_pos(active_extruder)); SERIAL_EOL;
  6012. SERIAL_ECHOPAIR("Lower to ", current_position[Z_AXIS]); SERIAL_EOL;
  6013. }
  6014. #endif
  6015. // Park old head: 1) raise 2) move to park position 3) lower
  6016. for (uint8_t i = 0; i < 3; i++)
  6017. planner.buffer_line(
  6018. i == 0 ? current_position[X_AXIS] : x_home_pos(active_extruder),
  6019. current_position[Y_AXIS],
  6020. current_position[Z_AXIS] + (i == 2 ? 0 : TOOLCHANGE_PARK_ZLIFT),
  6021. current_position[E_AXIS],
  6022. planner.max_feedrate_mm_s[i == 1 ? X_AXIS : Z_AXIS],
  6023. active_extruder
  6024. );
  6025. stepper.synchronize();
  6026. }
  6027. // apply Y & Z extruder offset (x offset is already used in determining home pos)
  6028. current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder];
  6029. current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder];
  6030. active_extruder = tmp_extruder;
  6031. // This function resets the max/min values - the current position may be overwritten below.
  6032. set_axis_is_at_home(X_AXIS);
  6033. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6034. if (DEBUGGING(LEVELING)) DEBUG_POS("New Extruder", current_position);
  6035. #endif
  6036. switch (dual_x_carriage_mode) {
  6037. case DXC_FULL_CONTROL_MODE:
  6038. current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos);
  6039. inactive_extruder_x_pos = RAW_X_POSITION(destination[X_AXIS]);
  6040. break;
  6041. case DXC_DUPLICATION_MODE:
  6042. active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
  6043. if (active_extruder_parked)
  6044. current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos);
  6045. else
  6046. current_position[X_AXIS] = destination[X_AXIS] + duplicate_extruder_x_offset;
  6047. inactive_extruder_x_pos = RAW_X_POSITION(destination[X_AXIS]);
  6048. extruder_duplication_enabled = false;
  6049. break;
  6050. default:
  6051. // record raised toolhead position for use by unpark
  6052. memcpy(raised_parked_position, current_position, sizeof(raised_parked_position));
  6053. raised_parked_position[Z_AXIS] += TOOLCHANGE_UNPARK_ZLIFT;
  6054. active_extruder_parked = true;
  6055. delayed_move_time = 0;
  6056. break;
  6057. }
  6058. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6059. if (DEBUGGING(LEVELING)) {
  6060. SERIAL_ECHOLNPAIR("Active extruder parked: ", active_extruder_parked ? "yes" : "no");
  6061. DEBUG_POS("New extruder (parked)", current_position);
  6062. }
  6063. #endif
  6064. // No extra case for HAS_ABL in DUAL_X_CARRIAGE. Does that mean they don't work together?
  6065. #else // !DUAL_X_CARRIAGE
  6066. #if ENABLED(SWITCHING_EXTRUDER)
  6067. // <0 if the new nozzle is higher, >0 if lower. A bigger raise when lower.
  6068. float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder],
  6069. z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0);
  6070. // Always raise by some amount
  6071. planner.buffer_line(
  6072. current_position[X_AXIS],
  6073. current_position[Y_AXIS],
  6074. current_position[Z_AXIS] + z_raise,
  6075. current_position[E_AXIS],
  6076. planner.max_feedrate_mm_s[Z_AXIS],
  6077. active_extruder
  6078. );
  6079. stepper.synchronize();
  6080. move_extruder_servo(active_extruder);
  6081. delay(500);
  6082. // Move back down, if needed
  6083. if (z_raise != z_diff) {
  6084. planner.buffer_line(
  6085. current_position[X_AXIS],
  6086. current_position[Y_AXIS],
  6087. current_position[Z_AXIS] + z_diff,
  6088. current_position[E_AXIS],
  6089. planner.max_feedrate_mm_s[Z_AXIS],
  6090. active_extruder
  6091. );
  6092. stepper.synchronize();
  6093. }
  6094. #endif
  6095. /**
  6096. * Set current_position to the position of the new nozzle.
  6097. * Offsets are based on linear distance, so we need to get
  6098. * the resulting position in coordinate space.
  6099. *
  6100. * - With grid or 3-point leveling, offset XYZ by a tilted vector
  6101. * - With mesh leveling, update Z for the new position
  6102. * - Otherwise, just use the raw linear distance
  6103. *
  6104. * Software endstops are altered here too. Consider a case where:
  6105. * E0 at X=0 ... E1 at X=10
  6106. * When we switch to E1 now X=10, but E1 can't move left.
  6107. * To express this we apply the change in XY to the software endstops.
  6108. * E1 can move farther right than E0, so the right limit is extended.
  6109. *
  6110. * Note that we don't adjust the Z software endstops. Why not?
  6111. * Consider a case where Z=0 (here) and switching to E1 makes Z=1
  6112. * because the bed is 1mm lower at the new position. As long as
  6113. * the first nozzle is out of the way, the carriage should be
  6114. * allowed to move 1mm lower. This technically "breaks" the
  6115. * Z software endstop. But this is technically correct (and
  6116. * there is no viable alternative).
  6117. */
  6118. #if ABL_PLANAR
  6119. // Offset extruder, make sure to apply the bed level rotation matrix
  6120. vector_3 tmp_offset_vec = vector_3(hotend_offset[X_AXIS][tmp_extruder],
  6121. hotend_offset[Y_AXIS][tmp_extruder],
  6122. 0),
  6123. act_offset_vec = vector_3(hotend_offset[X_AXIS][active_extruder],
  6124. hotend_offset[Y_AXIS][active_extruder],
  6125. 0),
  6126. offset_vec = tmp_offset_vec - act_offset_vec;
  6127. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6128. if (DEBUGGING(LEVELING)) {
  6129. tmp_offset_vec.debug("tmp_offset_vec");
  6130. act_offset_vec.debug("act_offset_vec");
  6131. offset_vec.debug("offset_vec (BEFORE)");
  6132. }
  6133. #endif
  6134. offset_vec.apply_rotation(planner.bed_level_matrix.transpose(planner.bed_level_matrix));
  6135. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6136. if (DEBUGGING(LEVELING)) offset_vec.debug("offset_vec (AFTER)");
  6137. #endif
  6138. // Adjustments to the current position
  6139. float xydiff[2] = { offset_vec.x, offset_vec.y };
  6140. current_position[Z_AXIS] += offset_vec.z;
  6141. #else // !ABL_PLANAR
  6142. float xydiff[2] = {
  6143. hotend_offset[X_AXIS][tmp_extruder] - hotend_offset[X_AXIS][active_extruder],
  6144. hotend_offset[Y_AXIS][tmp_extruder] - hotend_offset[Y_AXIS][active_extruder]
  6145. };
  6146. #if ENABLED(MESH_BED_LEVELING)
  6147. if (mbl.active()) {
  6148. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6149. if (DEBUGGING(LEVELING)) SERIAL_ECHOPAIR("Z before MBL: ", current_position[Z_AXIS]);
  6150. #endif
  6151. float xpos = RAW_CURRENT_POSITION(X_AXIS),
  6152. ypos = RAW_CURRENT_POSITION(Y_AXIS);
  6153. current_position[Z_AXIS] += mbl.get_z(xpos + xydiff[X_AXIS], ypos + xydiff[Y_AXIS]) - mbl.get_z(xpos, ypos);
  6154. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6155. if (DEBUGGING(LEVELING))
  6156. SERIAL_ECHOLNPAIR(" after: ", current_position[Z_AXIS]);
  6157. #endif
  6158. }
  6159. #endif // MESH_BED_LEVELING
  6160. #endif // !HAS_ABL
  6161. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6162. if (DEBUGGING(LEVELING)) {
  6163. SERIAL_ECHOPAIR("Offset Tool XY by { ", xydiff[X_AXIS]);
  6164. SERIAL_ECHOPAIR(", ", xydiff[Y_AXIS]);
  6165. SERIAL_ECHOLNPGM(" }");
  6166. }
  6167. #endif
  6168. // The newly-selected extruder XY is actually at...
  6169. current_position[X_AXIS] += xydiff[X_AXIS];
  6170. current_position[Y_AXIS] += xydiff[Y_AXIS];
  6171. for (uint8_t i = X_AXIS; i <= Y_AXIS; i++) {
  6172. position_shift[i] += xydiff[i];
  6173. update_software_endstops((AxisEnum)i);
  6174. }
  6175. // Set the new active extruder
  6176. active_extruder = tmp_extruder;
  6177. #endif // !DUAL_X_CARRIAGE
  6178. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6179. if (DEBUGGING(LEVELING)) DEBUG_POS("Sync After Toolchange", current_position);
  6180. #endif
  6181. // Tell the planner the new "current position"
  6182. SYNC_PLAN_POSITION_KINEMATIC();
  6183. // Move to the "old position" (move the extruder into place)
  6184. if (!no_move && IsRunning()) {
  6185. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6186. if (DEBUGGING(LEVELING)) DEBUG_POS("Move back", destination);
  6187. #endif
  6188. prepare_move_to_destination();
  6189. }
  6190. } // (tmp_extruder != active_extruder)
  6191. stepper.synchronize();
  6192. #if ENABLED(EXT_SOLENOID)
  6193. disable_all_solenoids();
  6194. enable_solenoid_on_active_extruder();
  6195. #endif // EXT_SOLENOID
  6196. feedrate_mm_s = old_feedrate_mm_s;
  6197. #else // HOTENDS <= 1
  6198. // Set the new active extruder
  6199. active_extruder = tmp_extruder;
  6200. UNUSED(fr_mm_s);
  6201. UNUSED(no_move);
  6202. #endif // HOTENDS <= 1
  6203. SERIAL_ECHO_START;
  6204. SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, (int)active_extruder);
  6205. #endif //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
  6206. }
  6207. /**
  6208. * T0-T3: Switch tool, usually switching extruders
  6209. *
  6210. * F[units/min] Set the movement feedrate
  6211. * S1 Don't move the tool in XY after change
  6212. */
  6213. inline void gcode_T(uint8_t tmp_extruder) {
  6214. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6215. if (DEBUGGING(LEVELING)) {
  6216. SERIAL_ECHOPAIR(">>> gcode_T(", tmp_extruder);
  6217. SERIAL_ECHOLNPGM(")");
  6218. DEBUG_POS("BEFORE", current_position);
  6219. }
  6220. #endif
  6221. #if HOTENDS == 1 || (ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1)
  6222. tool_change(tmp_extruder);
  6223. #elif HOTENDS > 1
  6224. tool_change(
  6225. tmp_extruder,
  6226. code_seen('F') ? MMM_TO_MMS(code_value_axis_units(X_AXIS)) : 0.0,
  6227. (tmp_extruder == active_extruder) || (code_seen('S') && code_value_bool())
  6228. );
  6229. #endif
  6230. #if ENABLED(DEBUG_LEVELING_FEATURE)
  6231. if (DEBUGGING(LEVELING)) {
  6232. DEBUG_POS("AFTER", current_position);
  6233. SERIAL_ECHOLNPGM("<<< gcode_T");
  6234. }
  6235. #endif
  6236. }
  6237. /**
  6238. * Process a single command and dispatch it to its handler
  6239. * This is called from the main loop()
  6240. */
  6241. void process_next_command() {
  6242. current_command = command_queue[cmd_queue_index_r];
  6243. if (DEBUGGING(ECHO)) {
  6244. SERIAL_ECHO_START;
  6245. SERIAL_ECHOLN(current_command);
  6246. }
  6247. // Sanitize the current command:
  6248. // - Skip leading spaces
  6249. // - Bypass N[-0-9][0-9]*[ ]*
  6250. // - Overwrite * with nul to mark the end
  6251. while (*current_command == ' ') ++current_command;
  6252. if (*current_command == 'N' && NUMERIC_SIGNED(current_command[1])) {
  6253. current_command += 2; // skip N[-0-9]
  6254. while (NUMERIC(*current_command)) ++current_command; // skip [0-9]*
  6255. while (*current_command == ' ') ++current_command; // skip [ ]*
  6256. }
  6257. char* starpos = strchr(current_command, '*'); // * should always be the last parameter
  6258. if (starpos) while (*starpos == ' ' || *starpos == '*') *starpos-- = '\0'; // nullify '*' and ' '
  6259. char *cmd_ptr = current_command;
  6260. // Get the command code, which must be G, M, or T
  6261. char command_code = *cmd_ptr++;
  6262. // Skip spaces to get the numeric part
  6263. while (*cmd_ptr == ' ') cmd_ptr++;
  6264. uint16_t codenum = 0; // define ahead of goto
  6265. // Bail early if there's no code
  6266. bool code_is_good = NUMERIC(*cmd_ptr);
  6267. if (!code_is_good) goto ExitUnknownCommand;
  6268. #ifdef G38_2_3
  6269. double codenum_float;
  6270. codenum_float = atof(cmd_ptr); //allow for decimal point in command
  6271. #endif
  6272. // Get and skip the code number
  6273. do {
  6274. codenum = (codenum * 10) + (*cmd_ptr - '0');
  6275. cmd_ptr++;
  6276. } while (NUMERIC(*cmd_ptr));
  6277. // Skip all spaces to get to the first argument, or nul
  6278. while (*cmd_ptr == ' ') cmd_ptr++;
  6279. // The command's arguments (if any) start here, for sure!
  6280. current_command_args = cmd_ptr;
  6281. KEEPALIVE_STATE(IN_HANDLER);
  6282. // Handle a known G, M, or T
  6283. switch (command_code) {
  6284. case 'G': switch (codenum) {
  6285. // G0, G1
  6286. case 0:
  6287. case 1:
  6288. #if IS_SCARA
  6289. gcode_G0_G1(codenum == 0);
  6290. #else
  6291. gcode_G0_G1();
  6292. #endif
  6293. break;
  6294. // G2, G3
  6295. #if ENABLED(ARC_SUPPORT) && DISABLED(SCARA)
  6296. case 2: // G2 - CW ARC
  6297. case 3: // G3 - CCW ARC
  6298. gcode_G2_G3(codenum == 2);
  6299. break;
  6300. #endif
  6301. // G4 Dwell
  6302. case 4:
  6303. gcode_G4();
  6304. break;
  6305. #if ENABLED(BEZIER_CURVE_SUPPORT)
  6306. // G5
  6307. case 5: // G5 - Cubic B_spline
  6308. gcode_G5();
  6309. break;
  6310. #endif // BEZIER_CURVE_SUPPORT
  6311. #if ENABLED(FWRETRACT)
  6312. case 10: // G10: retract
  6313. case 11: // G11: retract_recover
  6314. gcode_G10_G11(codenum == 10);
  6315. break;
  6316. #endif // FWRETRACT
  6317. #if ENABLED(NOZZLE_CLEAN_FEATURE)
  6318. case 12:
  6319. gcode_G12(); // G12: Nozzle Clean
  6320. break;
  6321. #endif // NOZZLE_CLEAN_FEATURE
  6322. #if ENABLED(INCH_MODE_SUPPORT)
  6323. case 20: //G20: Inch Mode
  6324. gcode_G20();
  6325. break;
  6326. case 21: //G21: MM Mode
  6327. gcode_G21();
  6328. break;
  6329. #endif // INCH_MODE_SUPPORT
  6330. #if ENABLED(NOZZLE_PARK_FEATURE)
  6331. case 27: // G27: Nozzle Park
  6332. gcode_G27();
  6333. break;
  6334. #endif // NOZZLE_PARK_FEATURE
  6335. case 28: // G28: Home all axes, one at a time
  6336. gcode_G28();
  6337. break;
  6338. #if PLANNER_LEVELING
  6339. case 29: // G29 Detailed Z probe, probes the bed at 3 or more points.
  6340. gcode_G29();
  6341. break;
  6342. #endif // PLANNER_LEVELING
  6343. #if HAS_BED_PROBE
  6344. case 30: // G30 Single Z probe
  6345. gcode_G30();
  6346. break;
  6347. #if ENABLED(Z_PROBE_SLED)
  6348. case 31: // G31: dock the sled
  6349. gcode_G31();
  6350. break;
  6351. case 32: // G32: undock the sled
  6352. gcode_G32();
  6353. break;
  6354. #endif // Z_PROBE_SLED
  6355. #endif // HAS_BED_PROBE
  6356. #ifdef G38_2_3
  6357. case 38: //G38.2 & G38.3
  6358. gcode_G38(codenum_float);
  6359. break;
  6360. #endif
  6361. case 90: // G90
  6362. relative_mode = false;
  6363. break;
  6364. case 91: // G91
  6365. relative_mode = true;
  6366. break;
  6367. case 92: // G92
  6368. gcode_G92();
  6369. break;
  6370. }
  6371. break;
  6372. case 'M': switch (codenum) {
  6373. #if ENABLED(ULTIPANEL) || ENABLED(EMERGENCY_PARSER)
  6374. case 0: // M0 - Unconditional stop - Wait for user button press on LCD
  6375. case 1: // M1 - Conditional stop - Wait for user button press on LCD
  6376. gcode_M0_M1();
  6377. break;
  6378. #endif // ULTIPANEL
  6379. case 17:
  6380. gcode_M17();
  6381. break;
  6382. #if ENABLED(SDSUPPORT)
  6383. case 20: // M20 - list SD card
  6384. gcode_M20(); break;
  6385. case 21: // M21 - init SD card
  6386. gcode_M21(); break;
  6387. case 22: //M22 - release SD card
  6388. gcode_M22(); break;
  6389. case 23: //M23 - Select file
  6390. gcode_M23(); break;
  6391. case 24: //M24 - Start SD print
  6392. gcode_M24(); break;
  6393. case 25: //M25 - Pause SD print
  6394. gcode_M25(); break;
  6395. case 26: //M26 - Set SD index
  6396. gcode_M26(); break;
  6397. case 27: //M27 - Get SD status
  6398. gcode_M27(); break;
  6399. case 28: //M28 - Start SD write
  6400. gcode_M28(); break;
  6401. case 29: //M29 - Stop SD write
  6402. gcode_M29(); break;
  6403. case 30: //M30 <filename> Delete File
  6404. gcode_M30(); break;
  6405. case 32: //M32 - Select file and start SD print
  6406. gcode_M32(); break;
  6407. #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
  6408. case 33: //M33 - Get the long full path to a file or folder
  6409. gcode_M33(); break;
  6410. #endif // LONG_FILENAME_HOST_SUPPORT
  6411. case 928: //M928 - Start SD write
  6412. gcode_M928(); break;
  6413. #endif //SDSUPPORT
  6414. case 31: //M31 take time since the start of the SD print or an M109 command
  6415. gcode_M31();
  6416. break;
  6417. case 42: //M42 -Change pin status via gcode
  6418. gcode_M42();
  6419. break;
  6420. #if ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST)
  6421. case 48: // M48 Z probe repeatability
  6422. gcode_M48();
  6423. break;
  6424. #endif // Z_MIN_PROBE_REPEATABILITY_TEST
  6425. case 75: // Start print timer
  6426. gcode_M75();
  6427. break;
  6428. case 76: // Pause print timer
  6429. gcode_M76();
  6430. break;
  6431. case 77: // Stop print timer
  6432. gcode_M77();
  6433. break;
  6434. #if ENABLED(PRINTCOUNTER)
  6435. case 78: // Show print statistics
  6436. gcode_M78();
  6437. break;
  6438. #endif
  6439. #if ENABLED(M100_FREE_MEMORY_WATCHER)
  6440. case 100:
  6441. gcode_M100();
  6442. break;
  6443. #endif
  6444. case 104: // M104
  6445. gcode_M104();
  6446. break;
  6447. case 110: // M110: Set Current Line Number
  6448. gcode_M110();
  6449. break;
  6450. case 111: // M111: Set debug level
  6451. gcode_M111();
  6452. break;
  6453. #if DISABLED(EMERGENCY_PARSER)
  6454. case 108: // M108: Cancel Waiting
  6455. gcode_M108();
  6456. break;
  6457. case 112: // M112: Emergency Stop
  6458. gcode_M112();
  6459. break;
  6460. case 410: // M410 quickstop - Abort all the planned moves.
  6461. gcode_M410();
  6462. break;
  6463. #endif
  6464. #if ENABLED(HOST_KEEPALIVE_FEATURE)
  6465. case 113: // M113: Set Host Keepalive interval
  6466. gcode_M113();
  6467. break;
  6468. #endif
  6469. case 140: // M140: Set bed temp
  6470. gcode_M140();
  6471. break;
  6472. case 105: // M105: Read current temperature
  6473. gcode_M105();
  6474. KEEPALIVE_STATE(NOT_BUSY);
  6475. return; // "ok" already printed
  6476. case 109: // M109: Wait for temperature
  6477. gcode_M109();
  6478. break;
  6479. #if HAS_TEMP_BED
  6480. case 190: // M190: Wait for bed heater to reach target
  6481. gcode_M190();
  6482. break;
  6483. #endif // HAS_TEMP_BED
  6484. #if FAN_COUNT > 0
  6485. case 106: // M106: Fan On
  6486. gcode_M106();
  6487. break;
  6488. case 107: // M107: Fan Off
  6489. gcode_M107();
  6490. break;
  6491. #endif // FAN_COUNT > 0
  6492. #if ENABLED(BARICUDA)
  6493. // PWM for HEATER_1_PIN
  6494. #if HAS_HEATER_1
  6495. case 126: // M126: valve open
  6496. gcode_M126();
  6497. break;
  6498. case 127: // M127: valve closed
  6499. gcode_M127();
  6500. break;
  6501. #endif // HAS_HEATER_1
  6502. // PWM for HEATER_2_PIN
  6503. #if HAS_HEATER_2
  6504. case 128: // M128: valve open
  6505. gcode_M128();
  6506. break;
  6507. case 129: // M129: valve closed
  6508. gcode_M129();
  6509. break;
  6510. #endif // HAS_HEATER_2
  6511. #endif // BARICUDA
  6512. #if HAS_POWER_SWITCH
  6513. case 80: // M80: Turn on Power Supply
  6514. gcode_M80();
  6515. break;
  6516. #endif // HAS_POWER_SWITCH
  6517. case 81: // M81: Turn off Power, including Power Supply, if possible
  6518. gcode_M81();
  6519. break;
  6520. case 82:
  6521. gcode_M82();
  6522. break;
  6523. case 83:
  6524. gcode_M83();
  6525. break;
  6526. case 18: // (for compatibility)
  6527. case 84: // M84
  6528. gcode_M18_M84();
  6529. break;
  6530. case 85: // M85
  6531. gcode_M85();
  6532. break;
  6533. case 92: // M92: Set the steps-per-unit for one or more axes
  6534. gcode_M92();
  6535. break;
  6536. case 115: // M115: Report capabilities
  6537. gcode_M115();
  6538. break;
  6539. case 117: // M117: Set LCD message text, if possible
  6540. gcode_M117();
  6541. break;
  6542. case 114: // M114: Report current position
  6543. gcode_M114();
  6544. break;
  6545. case 120: // M120: Enable endstops
  6546. gcode_M120();
  6547. break;
  6548. case 121: // M121: Disable endstops
  6549. gcode_M121();
  6550. break;
  6551. case 119: // M119: Report endstop states
  6552. gcode_M119();
  6553. break;
  6554. #if ENABLED(ULTIPANEL)
  6555. case 145: // M145: Set material heatup parameters
  6556. gcode_M145();
  6557. break;
  6558. #endif
  6559. #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
  6560. case 149:
  6561. gcode_M149();
  6562. break;
  6563. #endif
  6564. #if ENABLED(BLINKM)
  6565. case 150: // M150
  6566. gcode_M150();
  6567. break;
  6568. #endif //BLINKM
  6569. #if ENABLED(EXPERIMENTAL_I2CBUS)
  6570. case 155:
  6571. gcode_M155();
  6572. break;
  6573. case 156:
  6574. gcode_M156();
  6575. break;
  6576. #endif //EXPERIMENTAL_I2CBUS
  6577. #if ENABLED(MIXING_EXTRUDER)
  6578. case 163: // M163 S<int> P<float> set weight for a mixing extruder
  6579. gcode_M163();
  6580. break;
  6581. #if MIXING_VIRTUAL_TOOLS > 1
  6582. case 164: // M164 S<int> save current mix as a virtual extruder
  6583. gcode_M164();
  6584. break;
  6585. #endif
  6586. #if ENABLED(DIRECT_MIXING_IN_G1)
  6587. case 165: // M165 [ABCDHI]<float> set multiple mix weights
  6588. gcode_M165();
  6589. break;
  6590. #endif
  6591. #endif
  6592. case 200: // M200 D<diameter> Set filament diameter and set E axis units to cubic. (Use S0 to revert to linear units.)
  6593. gcode_M200();
  6594. break;
  6595. case 201: // M201
  6596. gcode_M201();
  6597. break;
  6598. #if 0 // Not used for Sprinter/grbl gen6
  6599. case 202: // M202
  6600. gcode_M202();
  6601. break;
  6602. #endif
  6603. case 203: // M203 max feedrate units/sec
  6604. gcode_M203();
  6605. break;
  6606. case 204: // M204 acclereration S normal moves T filmanent only moves
  6607. gcode_M204();
  6608. break;
  6609. case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
  6610. gcode_M205();
  6611. break;
  6612. case 206: // M206 additional homing offset
  6613. gcode_M206();
  6614. break;
  6615. #if ENABLED(DELTA)
  6616. case 665: // M665 set delta configurations L<diagonal_rod> R<delta_radius> S<segments_per_sec>
  6617. gcode_M665();
  6618. break;
  6619. #endif
  6620. #if ENABLED(DELTA) || ENABLED(Z_DUAL_ENDSTOPS)
  6621. case 666: // M666 set delta / dual endstop adjustment
  6622. gcode_M666();
  6623. break;
  6624. #endif
  6625. #if ENABLED(FWRETRACT)
  6626. case 207: // M207 - Set Retract Length: S<length>, Feedrate: F<units/min>, and Z lift: Z<distance>
  6627. gcode_M207();
  6628. break;
  6629. case 208: // M208 - Set Recover (unretract) Additional (!) Length: S<length> and Feedrate: F<units/min>
  6630. gcode_M208();
  6631. break;
  6632. case 209: // M209 - Turn Automatic Retract Detection on/off: S<bool> (For slicers that don't support G10/11). Every normal extrude-only move will be classified as retract depending on the direction.
  6633. gcode_M209();
  6634. break;
  6635. #endif // FWRETRACT
  6636. case 211: // M211 - Enable, Disable, and/or Report software endstops
  6637. gcode_M211();
  6638. break;
  6639. #if HOTENDS > 1
  6640. case 218: // M218 - Set a tool offset: T<index> X<offset> Y<offset>
  6641. gcode_M218();
  6642. break;
  6643. #endif
  6644. case 220: // M220 - Set Feedrate Percentage: S<percent> ("FR" on your LCD)
  6645. gcode_M220();
  6646. break;
  6647. case 221: // M221 - Set Flow Percentage: S<percent>
  6648. gcode_M221();
  6649. break;
  6650. case 226: // M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required
  6651. gcode_M226();
  6652. break;
  6653. #if HAS_SERVOS
  6654. case 280: // M280 - set servo position absolute. P: servo index, S: angle or microseconds
  6655. gcode_M280();
  6656. break;
  6657. #endif // HAS_SERVOS
  6658. #if HAS_BUZZER
  6659. case 300: // M300 - Play beep tone
  6660. gcode_M300();
  6661. break;
  6662. #endif // HAS_BUZZER
  6663. #if ENABLED(PIDTEMP)
  6664. case 301: // M301
  6665. gcode_M301();
  6666. break;
  6667. #endif // PIDTEMP
  6668. #if ENABLED(PIDTEMPBED)
  6669. case 304: // M304
  6670. gcode_M304();
  6671. break;
  6672. #endif // PIDTEMPBED
  6673. #if defined(CHDK) || HAS_PHOTOGRAPH
  6674. case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
  6675. gcode_M240();
  6676. break;
  6677. #endif // CHDK || PHOTOGRAPH_PIN
  6678. #if HAS_LCD_CONTRAST
  6679. case 250: // M250 Set LCD contrast value: C<value> (value 0..63)
  6680. gcode_M250();
  6681. break;
  6682. #endif // HAS_LCD_CONTRAST
  6683. #if ENABLED(PREVENT_COLD_EXTRUSION)
  6684. case 302: // allow cold extrudes, or set the minimum extrude temperature
  6685. gcode_M302();
  6686. break;
  6687. #endif // PREVENT_COLD_EXTRUSION
  6688. case 303: // M303 PID autotune
  6689. gcode_M303();
  6690. break;
  6691. #if ENABLED(MORGAN_SCARA)
  6692. case 360: // M360 SCARA Theta pos1
  6693. if (gcode_M360()) return;
  6694. break;
  6695. case 361: // M361 SCARA Theta pos2
  6696. if (gcode_M361()) return;
  6697. break;
  6698. case 362: // M362 SCARA Psi pos1
  6699. if (gcode_M362()) return;
  6700. break;
  6701. case 363: // M363 SCARA Psi pos2
  6702. if (gcode_M363()) return;
  6703. break;
  6704. case 364: // M364 SCARA Psi pos3 (90 deg to Theta)
  6705. if (gcode_M364()) return;
  6706. break;
  6707. #endif // SCARA
  6708. case 400: // M400 finish all moves
  6709. gcode_M400();
  6710. break;
  6711. #if HAS_BED_PROBE
  6712. case 401:
  6713. gcode_M401();
  6714. break;
  6715. case 402:
  6716. gcode_M402();
  6717. break;
  6718. #endif // HAS_BED_PROBE
  6719. #if ENABLED(FILAMENT_WIDTH_SENSOR)
  6720. case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or display nominal filament width
  6721. gcode_M404();
  6722. break;
  6723. case 405: //M405 Turn on filament sensor for control
  6724. gcode_M405();
  6725. break;
  6726. case 406: //M406 Turn off filament sensor for control
  6727. gcode_M406();
  6728. break;
  6729. case 407: //M407 Display measured filament diameter
  6730. gcode_M407();
  6731. break;
  6732. #endif // ENABLED(FILAMENT_WIDTH_SENSOR)
  6733. #if ENABLED(MESH_BED_LEVELING)
  6734. case 420: // M420 Enable/Disable Mesh Bed Leveling
  6735. gcode_M420();
  6736. break;
  6737. case 421: // M421 Set a Mesh Bed Leveling Z coordinate
  6738. gcode_M421();
  6739. break;
  6740. #endif
  6741. case 428: // M428 Apply current_position to home_offset
  6742. gcode_M428();
  6743. break;
  6744. case 500: // M500 Store settings in EEPROM
  6745. gcode_M500();
  6746. break;
  6747. case 501: // M501 Read settings from EEPROM
  6748. gcode_M501();
  6749. break;
  6750. case 502: // M502 Revert to default settings
  6751. gcode_M502();
  6752. break;
  6753. case 503: // M503 print settings currently in memory
  6754. gcode_M503();
  6755. break;
  6756. #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
  6757. case 540:
  6758. gcode_M540();
  6759. break;
  6760. #endif
  6761. #if HAS_BED_PROBE
  6762. case 851: // Set Z Probe Z Offset
  6763. gcode_M851();
  6764. break;
  6765. #endif // HAS_BED_PROBE
  6766. #if ENABLED(FILAMENT_CHANGE_FEATURE)
  6767. case 600: //Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
  6768. gcode_M600();
  6769. break;
  6770. #endif // FILAMENT_CHANGE_FEATURE
  6771. #if ENABLED(DUAL_X_CARRIAGE)
  6772. case 605:
  6773. gcode_M605();
  6774. break;
  6775. #endif // DUAL_X_CARRIAGE
  6776. #if ENABLED(LIN_ADVANCE)
  6777. case 905: // M905 Set advance factor.
  6778. gcode_M905();
  6779. break;
  6780. #endif
  6781. case 907: // M907 Set digital trimpot motor current using axis codes.
  6782. gcode_M907();
  6783. break;
  6784. #if HAS_DIGIPOTSS || ENABLED(DAC_STEPPER_CURRENT)
  6785. case 908: // M908 Control digital trimpot directly.
  6786. gcode_M908();
  6787. break;
  6788. #if ENABLED(DAC_STEPPER_CURRENT) // As with Printrbot RevF
  6789. case 909: // M909 Print digipot/DAC current value
  6790. gcode_M909();
  6791. break;
  6792. case 910: // M910 Commit digipot/DAC value to external EEPROM
  6793. gcode_M910();
  6794. break;
  6795. #endif
  6796. #endif // HAS_DIGIPOTSS || DAC_STEPPER_CURRENT
  6797. #if HAS_MICROSTEPS
  6798. case 350: // M350 Set microstepping mode. Warning: Steps per unit remains unchanged. S code sets stepping mode for all drivers.
  6799. gcode_M350();
  6800. break;
  6801. case 351: // M351 Toggle MS1 MS2 pins directly, S# determines MS1 or MS2, X# sets the pin high/low.
  6802. gcode_M351();
  6803. break;
  6804. #endif // HAS_MICROSTEPS
  6805. case 999: // M999: Restart after being Stopped
  6806. gcode_M999();
  6807. break;
  6808. }
  6809. break;
  6810. case 'T':
  6811. gcode_T(codenum);
  6812. break;
  6813. default: code_is_good = false;
  6814. }
  6815. KEEPALIVE_STATE(NOT_BUSY);
  6816. ExitUnknownCommand:
  6817. // Still unknown command? Throw an error
  6818. if (!code_is_good) unknown_command_error();
  6819. ok_to_send();
  6820. }
  6821. /**
  6822. * Send a "Resend: nnn" message to the host to
  6823. * indicate that a command needs to be re-sent.
  6824. */
  6825. void FlushSerialRequestResend() {
  6826. //char command_queue[cmd_queue_index_r][100]="Resend:";
  6827. MYSERIAL.flush();
  6828. SERIAL_PROTOCOLPGM(MSG_RESEND);
  6829. SERIAL_PROTOCOLLN(gcode_LastN + 1);
  6830. ok_to_send();
  6831. }
  6832. /**
  6833. * Send an "ok" message to the host, indicating
  6834. * that a command was successfully processed.
  6835. *
  6836. * If ADVANCED_OK is enabled also include:
  6837. * N<int> Line number of the command, if any
  6838. * P<int> Planner space remaining
  6839. * B<int> Block queue space remaining
  6840. */
  6841. void ok_to_send() {
  6842. refresh_cmd_timeout();
  6843. if (!send_ok[cmd_queue_index_r]) return;
  6844. SERIAL_PROTOCOLPGM(MSG_OK);
  6845. #if ENABLED(ADVANCED_OK)
  6846. char* p = command_queue[cmd_queue_index_r];
  6847. if (*p == 'N') {
  6848. SERIAL_PROTOCOL(' ');
  6849. SERIAL_ECHO(*p++);
  6850. while (NUMERIC_SIGNED(*p))
  6851. SERIAL_ECHO(*p++);
  6852. }
  6853. SERIAL_PROTOCOLPGM(" P"); SERIAL_PROTOCOL(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
  6854. SERIAL_PROTOCOLPGM(" B"); SERIAL_PROTOCOL(BUFSIZE - commands_in_queue);
  6855. #endif
  6856. SERIAL_EOL;
  6857. }
  6858. #if ENABLED(min_software_endstops) || ENABLED(max_software_endstops)
  6859. /**
  6860. * Constrain the given coordinates to the software endstops.
  6861. */
  6862. void clamp_to_software_endstops(float target[XYZ]) {
  6863. #if ENABLED(min_software_endstops)
  6864. NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]);
  6865. NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]);
  6866. NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]);
  6867. #endif
  6868. #if ENABLED(max_software_endstops)
  6869. NOMORE(target[X_AXIS], soft_endstop_max[X_AXIS]);
  6870. NOMORE(target[Y_AXIS], soft_endstop_max[Y_AXIS]);
  6871. NOMORE(target[Z_AXIS], soft_endstop_max[Z_AXIS]);
  6872. #endif
  6873. }
  6874. #endif
  6875. #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
  6876. // Get the Z adjustment for non-linear bed leveling
  6877. float bilinear_z_offset(float cartesian[XYZ]) {
  6878. // XY relative to the probed area
  6879. const float x = RAW_X_POSITION(cartesian[X_AXIS]) - bilinear_start[X_AXIS],
  6880. y = RAW_Y_POSITION(cartesian[Y_AXIS]) - bilinear_start[Y_AXIS];
  6881. // Convert to grid box units
  6882. float ratio_x = x / bilinear_grid_spacing[X_AXIS],
  6883. ratio_y = y / bilinear_grid_spacing[Y_AXIS];
  6884. // Whole unit is the grid box index
  6885. const int gridx = constrain(floor(ratio_x), 0, ABL_GRID_POINTS_X - 2),
  6886. gridy = constrain(floor(ratio_y), 0, ABL_GRID_POINTS_Y - 2),
  6887. nextx = gridx + (x < PROBE_BED_WIDTH ? 1 : 0),
  6888. nexty = gridy + (y < PROBE_BED_HEIGHT ? 1 : 0);
  6889. // Subtract whole to get the ratio within the grid box
  6890. ratio_x = constrain(ratio_x - gridx, 0.0, 1.0);
  6891. ratio_y = constrain(ratio_y - gridy, 0.0, 1.0);
  6892. // Z at the box corners
  6893. const float z1 = bed_level_grid[gridx][gridy], // left-front
  6894. z2 = bed_level_grid[gridx][nexty], // left-back
  6895. z3 = bed_level_grid[nextx][gridy], // right-front
  6896. z4 = bed_level_grid[nextx][nexty], // right-back
  6897. // Bilinear interpolate
  6898. L = z1 + (z2 - z1) * ratio_y, // Linear interp. LF -> LB
  6899. R = z3 + (z4 - z3) * ratio_y, // Linear interp. RF -> RB
  6900. offset = L + ratio_x * (R - L);
  6901. /*
  6902. static float last_offset = 0;
  6903. if (fabs(last_offset - offset) > 0.2) {
  6904. SERIAL_ECHOPGM("Sudden Shift at ");
  6905. SERIAL_ECHOPAIR("x=", x);
  6906. SERIAL_ECHOPAIR(" / ", bilinear_grid_spacing[X_AXIS]);
  6907. SERIAL_ECHOLNPAIR(" -> gridx=", gridx);
  6908. SERIAL_ECHOPAIR(" y=", y);
  6909. SERIAL_ECHOPAIR(" / ", bilinear_grid_spacing[Y_AXIS]);
  6910. SERIAL_ECHOLNPAIR(" -> gridy=", gridy);
  6911. SERIAL_ECHOPAIR(" ratio_x=", ratio_x);
  6912. SERIAL_ECHOLNPAIR(" ratio_y=", ratio_y);
  6913. SERIAL_ECHOPAIR(" z1=", z1);
  6914. SERIAL_ECHOPAIR(" z2=", z2);
  6915. SERIAL_ECHOPAIR(" z3=", z3);
  6916. SERIAL_ECHOLNPAIR(" z4=", z4);
  6917. SERIAL_ECHOPAIR(" L=", L);
  6918. SERIAL_ECHOPAIR(" R=", R);
  6919. SERIAL_ECHOLNPAIR(" offset=", offset);
  6920. }
  6921. last_offset = offset;
  6922. //*/
  6923. return offset;
  6924. }
  6925. #endif // AUTO_BED_LEVELING_BILINEAR
  6926. #if ENABLED(DELTA)
  6927. /**
  6928. * Recalculate factors used for delta kinematics whenever
  6929. * settings have been changed (e.g., by M665).
  6930. */
  6931. void recalc_delta_settings(float radius, float diagonal_rod) {
  6932. delta_tower1_x = -SIN_60 * (radius + DELTA_RADIUS_TRIM_TOWER_1); // front left tower
  6933. delta_tower1_y = -COS_60 * (radius + DELTA_RADIUS_TRIM_TOWER_1);
  6934. delta_tower2_x = SIN_60 * (radius + DELTA_RADIUS_TRIM_TOWER_2); // front right tower
  6935. delta_tower2_y = -COS_60 * (radius + DELTA_RADIUS_TRIM_TOWER_2);
  6936. delta_tower3_x = 0.0; // back middle tower
  6937. delta_tower3_y = (radius + DELTA_RADIUS_TRIM_TOWER_3);
  6938. delta_diagonal_rod_2_tower_1 = sq(diagonal_rod + delta_diagonal_rod_trim_tower_1);
  6939. delta_diagonal_rod_2_tower_2 = sq(diagonal_rod + delta_diagonal_rod_trim_tower_2);
  6940. delta_diagonal_rod_2_tower_3 = sq(diagonal_rod + delta_diagonal_rod_trim_tower_3);
  6941. }
  6942. #if ENABLED(DELTA_FAST_SQRT)
  6943. /**
  6944. * Fast inverse sqrt from Quake III Arena
  6945. * See: https://en.wikipedia.org/wiki/Fast_inverse_square_root
  6946. */
  6947. float Q_rsqrt(float number) {
  6948. long i;
  6949. float x2, y;
  6950. const float threehalfs = 1.5f;
  6951. x2 = number * 0.5f;
  6952. y = number;
  6953. i = * ( long * ) &y; // evil floating point bit level hacking
  6954. i = 0x5f3759df - ( i >> 1 ); // what the f***?
  6955. y = * ( float * ) &i;
  6956. y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  6957. // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  6958. return y;
  6959. }
  6960. #define _SQRT(n) (1.0f / Q_rsqrt(n))
  6961. #else
  6962. #define _SQRT(n) sqrt(n)
  6963. #endif
  6964. /**
  6965. * Delta Inverse Kinematics
  6966. *
  6967. * Calculate the tower positions for a given logical
  6968. * position, storing the result in the delta[] array.
  6969. *
  6970. * This is an expensive calculation, requiring 3 square
  6971. * roots per segmented linear move, and strains the limits
  6972. * of a Mega2560 with a Graphical Display.
  6973. *
  6974. * Suggested optimizations include:
  6975. *
  6976. * - Disable the home_offset (M206) and/or position_shift (G92)
  6977. * features to remove up to 12 float additions.
  6978. *
  6979. * - Use a fast-inverse-sqrt function and add the reciprocal.
  6980. * (see above)
  6981. */
  6982. // Macro to obtain the Z position of an individual tower
  6983. #define DELTA_Z(T) raw[Z_AXIS] + _SQRT( \
  6984. delta_diagonal_rod_2_tower_##T - HYPOT2( \
  6985. delta_tower##T##_x - raw[X_AXIS], \
  6986. delta_tower##T##_y - raw[Y_AXIS] \
  6987. ) \
  6988. )
  6989. #define DELTA_RAW_IK() do { \
  6990. delta[A_AXIS] = DELTA_Z(1); \
  6991. delta[B_AXIS] = DELTA_Z(2); \
  6992. delta[C_AXIS] = DELTA_Z(3); \
  6993. } while(0)
  6994. #define DELTA_LOGICAL_IK() do { \
  6995. const float raw[XYZ] = { \
  6996. RAW_X_POSITION(logical[X_AXIS]), \
  6997. RAW_Y_POSITION(logical[Y_AXIS]), \
  6998. RAW_Z_POSITION(logical[Z_AXIS]) \
  6999. }; \
  7000. DELTA_RAW_IK(); \
  7001. } while(0)
  7002. #define DELTA_DEBUG() do { \
  7003. SERIAL_ECHOPAIR("cartesian X:", raw[X_AXIS]); \
  7004. SERIAL_ECHOPAIR(" Y:", raw[Y_AXIS]); \
  7005. SERIAL_ECHOLNPAIR(" Z:", raw[Z_AXIS]); \
  7006. SERIAL_ECHOPAIR("delta A:", delta[A_AXIS]); \
  7007. SERIAL_ECHOPAIR(" B:", delta[B_AXIS]); \
  7008. SERIAL_ECHOLNPAIR(" C:", delta[C_AXIS]); \
  7009. } while(0)
  7010. void inverse_kinematics(const float logical[XYZ]) {
  7011. DELTA_LOGICAL_IK();
  7012. // DELTA_DEBUG();
  7013. }
  7014. /**
  7015. * Calculate the highest Z position where the
  7016. * effector has the full range of XY motion.
  7017. */
  7018. float delta_safe_distance_from_top() {
  7019. float cartesian[XYZ] = {
  7020. LOGICAL_X_POSITION(0),
  7021. LOGICAL_Y_POSITION(0),
  7022. LOGICAL_Z_POSITION(0)
  7023. };
  7024. inverse_kinematics(cartesian);
  7025. float distance = delta[A_AXIS];
  7026. cartesian[Y_AXIS] = LOGICAL_Y_POSITION(DELTA_PRINTABLE_RADIUS);
  7027. inverse_kinematics(cartesian);
  7028. return abs(distance - delta[A_AXIS]);
  7029. }
  7030. /**
  7031. * Delta Forward Kinematics
  7032. *
  7033. * See the Wikipedia article "Trilateration"
  7034. * https://en.wikipedia.org/wiki/Trilateration
  7035. *
  7036. * Establish a new coordinate system in the plane of the
  7037. * three carriage points. This system has its origin at
  7038. * tower1, with tower2 on the X axis. Tower3 is in the X-Y
  7039. * plane with a Z component of zero.
  7040. * We will define unit vectors in this coordinate system
  7041. * in our original coordinate system. Then when we calculate
  7042. * the Xnew, Ynew and Znew values, we can translate back into
  7043. * the original system by moving along those unit vectors
  7044. * by the corresponding values.
  7045. *
  7046. * Variable names matched to Marlin, c-version, and avoid the
  7047. * use of any vector library.
  7048. *
  7049. * by Andreas Hardtung 2016-06-07
  7050. * based on a Java function from "Delta Robot Kinematics V3"
  7051. * by Steve Graves
  7052. *
  7053. * The result is stored in the cartes[] array.
  7054. */
  7055. void forward_kinematics_DELTA(float z1, float z2, float z3) {
  7056. // Create a vector in old coordinates along x axis of new coordinate
  7057. float p12[3] = { delta_tower2_x - delta_tower1_x, delta_tower2_y - delta_tower1_y, z2 - z1 };
  7058. // Get the Magnitude of vector.
  7059. float d = sqrt( sq(p12[0]) + sq(p12[1]) + sq(p12[2]) );
  7060. // Create unit vector by dividing by magnitude.
  7061. float ex[3] = { p12[0] / d, p12[1] / d, p12[2] / d };
  7062. // Get the vector from the origin of the new system to the third point.
  7063. float p13[3] = { delta_tower3_x - delta_tower1_x, delta_tower3_y - delta_tower1_y, z3 - z1 };
  7064. // Use the dot product to find the component of this vector on the X axis.
  7065. float i = ex[0] * p13[0] + ex[1] * p13[1] + ex[2] * p13[2];
  7066. // Create a vector along the x axis that represents the x component of p13.
  7067. float iex[3] = { ex[0] * i, ex[1] * i, ex[2] * i };
  7068. // Subtract the X component from the original vector leaving only Y. We use the
  7069. // variable that will be the unit vector after we scale it.
  7070. float ey[3] = { p13[0] - iex[0], p13[1] - iex[1], p13[2] - iex[2] };
  7071. // The magnitude of Y component
  7072. float j = sqrt( sq(ey[0]) + sq(ey[1]) + sq(ey[2]) );
  7073. // Convert to a unit vector
  7074. ey[0] /= j; ey[1] /= j; ey[2] /= j;
  7075. // The cross product of the unit x and y is the unit z
  7076. // float[] ez = vectorCrossProd(ex, ey);
  7077. float ez[3] = {
  7078. ex[1] * ey[2] - ex[2] * ey[1],
  7079. ex[2] * ey[0] - ex[0] * ey[2],
  7080. ex[0] * ey[1] - ex[1] * ey[0]
  7081. };
  7082. // We now have the d, i and j values defined in Wikipedia.
  7083. // Plug them into the equations defined in Wikipedia for Xnew, Ynew and Znew
  7084. float Xnew = (delta_diagonal_rod_2_tower_1 - delta_diagonal_rod_2_tower_2 + sq(d)) / (d * 2),
  7085. Ynew = ((delta_diagonal_rod_2_tower_1 - delta_diagonal_rod_2_tower_3 + HYPOT2(i, j)) / 2 - i * Xnew) / j,
  7086. Znew = sqrt(delta_diagonal_rod_2_tower_1 - HYPOT2(Xnew, Ynew));
  7087. // Start from the origin of the old coordinates and add vectors in the
  7088. // old coords that represent the Xnew, Ynew and Znew to find the point
  7089. // in the old system.
  7090. cartes[X_AXIS] = delta_tower1_x + ex[0] * Xnew + ey[0] * Ynew - ez[0] * Znew;
  7091. cartes[Y_AXIS] = delta_tower1_y + ex[1] * Xnew + ey[1] * Ynew - ez[1] * Znew;
  7092. cartes[Z_AXIS] = z1 + ex[2] * Xnew + ey[2] * Ynew - ez[2] * Znew;
  7093. };
  7094. void forward_kinematics_DELTA(float point[ABC]) {
  7095. forward_kinematics_DELTA(point[A_AXIS], point[B_AXIS], point[C_AXIS]);
  7096. }
  7097. #endif // DELTA
  7098. /**
  7099. * Get the stepper positions in the cartes[] array.
  7100. * Forward kinematics are applied for DELTA and SCARA.
  7101. *
  7102. * The result is in the current coordinate space with
  7103. * leveling applied. The coordinates need to be run through
  7104. * unapply_leveling to obtain the "ideal" coordinates
  7105. * suitable for current_position, etc.
  7106. */
  7107. void get_cartesian_from_steppers() {
  7108. #if ENABLED(DELTA)
  7109. forward_kinematics_DELTA(
  7110. stepper.get_axis_position_mm(A_AXIS),
  7111. stepper.get_axis_position_mm(B_AXIS),
  7112. stepper.get_axis_position_mm(C_AXIS)
  7113. );
  7114. cartes[X_AXIS] += LOGICAL_X_POSITION(0);
  7115. cartes[Y_AXIS] += LOGICAL_Y_POSITION(0);
  7116. cartes[Z_AXIS] += LOGICAL_Z_POSITION(0);
  7117. #elif IS_SCARA
  7118. forward_kinematics_SCARA(
  7119. stepper.get_axis_position_degrees(A_AXIS),
  7120. stepper.get_axis_position_degrees(B_AXIS)
  7121. );
  7122. cartes[X_AXIS] += LOGICAL_X_POSITION(0);
  7123. cartes[Y_AXIS] += LOGICAL_Y_POSITION(0);
  7124. cartes[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
  7125. #else
  7126. cartes[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
  7127. cartes[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
  7128. cartes[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
  7129. #endif
  7130. }
  7131. /**
  7132. * Set the current_position for an axis based on
  7133. * the stepper positions, removing any leveling that
  7134. * may have been applied.
  7135. */
  7136. void set_current_from_steppers_for_axis(const AxisEnum axis) {
  7137. get_cartesian_from_steppers();
  7138. #if PLANNER_LEVELING
  7139. planner.unapply_leveling(cartes);
  7140. #endif
  7141. if (axis == ALL_AXES)
  7142. memcpy(current_position, cartes, sizeof(cartes));
  7143. else
  7144. current_position[axis] = cartes[axis];
  7145. }
  7146. #if ENABLED(MESH_BED_LEVELING)
  7147. /**
  7148. * Prepare a mesh-leveled linear move in a Cartesian setup,
  7149. * splitting the move where it crosses mesh borders.
  7150. */
  7151. void mesh_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_splits = 0xff) {
  7152. int cx1 = mbl.cell_index_x(RAW_CURRENT_POSITION(X_AXIS)),
  7153. cy1 = mbl.cell_index_y(RAW_CURRENT_POSITION(Y_AXIS)),
  7154. cx2 = mbl.cell_index_x(RAW_X_POSITION(destination[X_AXIS])),
  7155. cy2 = mbl.cell_index_y(RAW_Y_POSITION(destination[Y_AXIS]));
  7156. NOMORE(cx1, MESH_NUM_X_POINTS - 2);
  7157. NOMORE(cy1, MESH_NUM_Y_POINTS - 2);
  7158. NOMORE(cx2, MESH_NUM_X_POINTS - 2);
  7159. NOMORE(cy2, MESH_NUM_Y_POINTS - 2);
  7160. if (cx1 == cx2 && cy1 == cy2) {
  7161. // Start and end on same mesh square
  7162. line_to_destination(fr_mm_s);
  7163. set_current_to_destination();
  7164. return;
  7165. }
  7166. #define MBL_SEGMENT_END(A) (current_position[A ##_AXIS] + (destination[A ##_AXIS] - current_position[A ##_AXIS]) * normalized_dist)
  7167. float normalized_dist, end[NUM_AXIS];
  7168. // Split at the left/front border of the right/top square
  7169. int8_t gcx = max(cx1, cx2), gcy = max(cy1, cy2);
  7170. if (cx2 != cx1 && TEST(x_splits, gcx)) {
  7171. memcpy(end, destination, sizeof(end));
  7172. destination[X_AXIS] = LOGICAL_X_POSITION(mbl.get_probe_x(gcx));
  7173. normalized_dist = (destination[X_AXIS] - current_position[X_AXIS]) / (end[X_AXIS] - current_position[X_AXIS]);
  7174. destination[Y_AXIS] = MBL_SEGMENT_END(Y);
  7175. CBI(x_splits, gcx);
  7176. }
  7177. else if (cy2 != cy1 && TEST(y_splits, gcy)) {
  7178. memcpy(end, destination, sizeof(end));
  7179. destination[Y_AXIS] = LOGICAL_Y_POSITION(mbl.get_probe_y(gcy));
  7180. normalized_dist = (destination[Y_AXIS] - current_position[Y_AXIS]) / (end[Y_AXIS] - current_position[Y_AXIS]);
  7181. destination[X_AXIS] = MBL_SEGMENT_END(X);
  7182. CBI(y_splits, gcy);
  7183. }
  7184. else {
  7185. // Already split on a border
  7186. line_to_destination(fr_mm_s);
  7187. set_current_to_destination();
  7188. return;
  7189. }
  7190. destination[Z_AXIS] = MBL_SEGMENT_END(Z);
  7191. destination[E_AXIS] = MBL_SEGMENT_END(E);
  7192. // Do the split and look for more borders
  7193. mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
  7194. // Restore destination from stack
  7195. memcpy(destination, end, sizeof(end));
  7196. mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
  7197. }
  7198. #endif // MESH_BED_LEVELING
  7199. #if IS_KINEMATIC
  7200. /**
  7201. * Prepare a linear move in a DELTA or SCARA setup.
  7202. *
  7203. * This calls planner.buffer_line several times, adding
  7204. * small incremental moves for DELTA or SCARA.
  7205. */
  7206. inline bool prepare_kinematic_move_to(float ltarget[NUM_AXIS]) {
  7207. // Get the top feedrate of the move in the XY plane
  7208. float _feedrate_mm_s = MMS_SCALED(feedrate_mm_s);
  7209. // If the move is only in Z/E don't split up the move
  7210. if (ltarget[X_AXIS] == current_position[X_AXIS] && ltarget[Y_AXIS] == current_position[Y_AXIS]) {
  7211. inverse_kinematics(ltarget);
  7212. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], _feedrate_mm_s, active_extruder);
  7213. return true;
  7214. }
  7215. // Get the cartesian distances moved in XYZE
  7216. float difference[NUM_AXIS];
  7217. LOOP_XYZE(i) difference[i] = ltarget[i] - current_position[i];
  7218. // Get the linear distance in XYZ
  7219. float cartesian_mm = sqrt(sq(difference[X_AXIS]) + sq(difference[Y_AXIS]) + sq(difference[Z_AXIS]));
  7220. // If the move is very short, check the E move distance
  7221. if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = abs(difference[E_AXIS]);
  7222. // No E move either? Game over.
  7223. if (UNEAR_ZERO(cartesian_mm)) return false;
  7224. // Minimum number of seconds to move the given distance
  7225. float seconds = cartesian_mm / _feedrate_mm_s;
  7226. // The number of segments-per-second times the duration
  7227. // gives the number of segments
  7228. uint16_t segments = delta_segments_per_second * seconds;
  7229. // For SCARA minimum segment size is 0.5mm
  7230. #if IS_SCARA
  7231. NOMORE(segments, cartesian_mm * 2);
  7232. #endif
  7233. // At least one segment is required
  7234. NOLESS(segments, 1);
  7235. // The approximate length of each segment
  7236. float segment_distance[XYZE] = {
  7237. difference[X_AXIS] / segments,
  7238. difference[Y_AXIS] / segments,
  7239. difference[Z_AXIS] / segments,
  7240. difference[E_AXIS] / segments
  7241. };
  7242. // SERIAL_ECHOPAIR("mm=", cartesian_mm);
  7243. // SERIAL_ECHOPAIR(" seconds=", seconds);
  7244. // SERIAL_ECHOLNPAIR(" segments=", segments);
  7245. // Drop one segment so the last move is to the exact target.
  7246. // If there's only 1 segment, loops will be skipped entirely.
  7247. --segments;
  7248. // Using "raw" coordinates saves 6 float subtractions
  7249. // per segment, saving valuable CPU cycles
  7250. #if ENABLED(USE_RAW_KINEMATICS)
  7251. // Get the raw current position as starting point
  7252. float raw[XYZE] = {
  7253. RAW_CURRENT_POSITION(X_AXIS),
  7254. RAW_CURRENT_POSITION(Y_AXIS),
  7255. RAW_CURRENT_POSITION(Z_AXIS),
  7256. current_position[E_AXIS]
  7257. };
  7258. #define DELTA_VAR raw
  7259. // Delta can inline its kinematics
  7260. #if ENABLED(DELTA)
  7261. #define DELTA_IK() DELTA_RAW_IK()
  7262. #else
  7263. #define DELTA_IK() inverse_kinematics(raw)
  7264. #endif
  7265. #else
  7266. // Get the logical current position as starting point
  7267. float logical[XYZE];
  7268. memcpy(logical, current_position, sizeof(logical));
  7269. #define DELTA_VAR logical
  7270. // Delta can inline its kinematics
  7271. #if ENABLED(DELTA)
  7272. #define DELTA_IK() DELTA_LOGICAL_IK()
  7273. #else
  7274. #define DELTA_IK() inverse_kinematics(logical)
  7275. #endif
  7276. #endif
  7277. #if ENABLED(USE_DELTA_IK_INTERPOLATION)
  7278. // Only interpolate XYZ. Advance E normally.
  7279. #define DELTA_NEXT(ADDEND) LOOP_XYZ(i) DELTA_VAR[i] += ADDEND;
  7280. // Get the starting delta if interpolation is possible
  7281. if (segments >= 2) DELTA_IK();
  7282. // Loop using decrement
  7283. for (uint16_t s = segments + 1; --s;) {
  7284. // Are there at least 2 moves left?
  7285. if (s >= 2) {
  7286. // Save the previous delta for interpolation
  7287. float prev_delta[ABC] = { delta[A_AXIS], delta[B_AXIS], delta[C_AXIS] };
  7288. // Get the delta 2 segments ahead (rather than the next)
  7289. DELTA_NEXT(segment_distance[i] + segment_distance[i]);
  7290. // Advance E normally
  7291. DELTA_VAR[E_AXIS] += segment_distance[E_AXIS];
  7292. // Get the exact delta for the move after this
  7293. DELTA_IK();
  7294. // Move to the interpolated delta position first
  7295. planner.buffer_line(
  7296. (prev_delta[A_AXIS] + delta[A_AXIS]) * 0.5,
  7297. (prev_delta[B_AXIS] + delta[B_AXIS]) * 0.5,
  7298. (prev_delta[C_AXIS] + delta[C_AXIS]) * 0.5,
  7299. DELTA_VAR[E_AXIS], _feedrate_mm_s, active_extruder
  7300. );
  7301. // Advance E once more for the next move
  7302. DELTA_VAR[E_AXIS] += segment_distance[E_AXIS];
  7303. // Do an extra decrement of the loop
  7304. --s;
  7305. }
  7306. else {
  7307. // Get the last segment delta. (Used when segments is odd)
  7308. DELTA_NEXT(segment_distance[i]);
  7309. DELTA_VAR[E_AXIS] += segment_distance[E_AXIS];
  7310. DELTA_IK();
  7311. }
  7312. // Move to the non-interpolated position
  7313. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], DELTA_VAR[E_AXIS], _feedrate_mm_s, active_extruder);
  7314. }
  7315. #else
  7316. #define DELTA_NEXT(ADDEND) LOOP_XYZE(i) DELTA_VAR[i] += ADDEND;
  7317. // For non-interpolated delta calculate every segment
  7318. for (uint16_t s = segments + 1; --s;) {
  7319. DELTA_NEXT(segment_distance[i]);
  7320. DELTA_IK();
  7321. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], DELTA_VAR[E_AXIS], _feedrate_mm_s, active_extruder);
  7322. }
  7323. #endif
  7324. // Since segment_distance is only approximate,
  7325. // the final move must be to the exact destination.
  7326. inverse_kinematics(ltarget);
  7327. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], _feedrate_mm_s, active_extruder);
  7328. return true;
  7329. }
  7330. #else
  7331. /**
  7332. * Prepare a linear move in a Cartesian setup.
  7333. * If Mesh Bed Leveling is enabled, perform a mesh move.
  7334. */
  7335. inline bool prepare_move_to_destination_cartesian() {
  7336. // Do not use feedrate_percentage for E or Z only moves
  7337. if (current_position[X_AXIS] == destination[X_AXIS] && current_position[Y_AXIS] == destination[Y_AXIS]) {
  7338. line_to_destination();
  7339. }
  7340. else {
  7341. #if ENABLED(MESH_BED_LEVELING)
  7342. if (mbl.active()) {
  7343. mesh_line_to_destination(MMS_SCALED(feedrate_mm_s));
  7344. return false;
  7345. }
  7346. else
  7347. #endif
  7348. line_to_destination(MMS_SCALED(feedrate_mm_s));
  7349. }
  7350. return true;
  7351. }
  7352. #endif // !IS_KINEMATIC
  7353. #if ENABLED(DUAL_X_CARRIAGE)
  7354. /**
  7355. * Prepare a linear move in a dual X axis setup
  7356. */
  7357. inline bool prepare_move_to_destination_dualx() {
  7358. if (active_extruder_parked) {
  7359. if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && active_extruder == 0) {
  7360. // move duplicate extruder into correct duplication position.
  7361. planner.set_position_mm(
  7362. LOGICAL_X_POSITION(inactive_extruder_x_pos),
  7363. current_position[Y_AXIS],
  7364. current_position[Z_AXIS],
  7365. current_position[E_AXIS]
  7366. );
  7367. planner.buffer_line(current_position[X_AXIS] + duplicate_extruder_x_offset,
  7368. current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], planner.max_feedrate_mm_s[X_AXIS], 1);
  7369. SYNC_PLAN_POSITION_KINEMATIC();
  7370. stepper.synchronize();
  7371. extruder_duplication_enabled = true;
  7372. active_extruder_parked = false;
  7373. }
  7374. else if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE) { // handle unparking of head
  7375. if (current_position[E_AXIS] == destination[E_AXIS]) {
  7376. // This is a travel move (with no extrusion)
  7377. // Skip it, but keep track of the current position
  7378. // (so it can be used as the start of the next non-travel move)
  7379. if (delayed_move_time != 0xFFFFFFFFUL) {
  7380. set_current_to_destination();
  7381. NOLESS(raised_parked_position[Z_AXIS], destination[Z_AXIS]);
  7382. delayed_move_time = millis();
  7383. return false;
  7384. }
  7385. }
  7386. delayed_move_time = 0;
  7387. // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
  7388. planner.buffer_line(raised_parked_position[X_AXIS], raised_parked_position[Y_AXIS], raised_parked_position[Z_AXIS], current_position[E_AXIS], planner.max_feedrate_mm_s[Z_AXIS], active_extruder);
  7389. planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], raised_parked_position[Z_AXIS], current_position[E_AXIS], PLANNER_XY_FEEDRATE(), active_extruder);
  7390. planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], planner.max_feedrate_mm_s[Z_AXIS], active_extruder);
  7391. active_extruder_parked = false;
  7392. }
  7393. }
  7394. return true;
  7395. }
  7396. #endif // DUAL_X_CARRIAGE
  7397. /**
  7398. * Prepare a single move and get ready for the next one
  7399. *
  7400. * This may result in several calls to planner.buffer_line to
  7401. * do smaller moves for DELTA, SCARA, mesh moves, etc.
  7402. */
  7403. void prepare_move_to_destination() {
  7404. clamp_to_software_endstops(destination);
  7405. refresh_cmd_timeout();
  7406. #if ENABLED(PREVENT_COLD_EXTRUSION)
  7407. if (!DEBUGGING(DRYRUN)) {
  7408. if (destination[E_AXIS] != current_position[E_AXIS]) {
  7409. if (thermalManager.tooColdToExtrude(active_extruder)) {
  7410. current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part
  7411. SERIAL_ECHO_START;
  7412. SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
  7413. }
  7414. #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
  7415. if (labs(destination[E_AXIS] - current_position[E_AXIS]) > EXTRUDE_MAXLENGTH) {
  7416. current_position[E_AXIS] = destination[E_AXIS]; // Behave as if the move really took place, but ignore E part
  7417. SERIAL_ECHO_START;
  7418. SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP);
  7419. }
  7420. #endif
  7421. }
  7422. }
  7423. #endif
  7424. #if IS_KINEMATIC
  7425. if (!prepare_kinematic_move_to(destination)) return;
  7426. #else
  7427. #if ENABLED(DUAL_X_CARRIAGE)
  7428. if (!prepare_move_to_destination_dualx()) return;
  7429. #endif
  7430. if (!prepare_move_to_destination_cartesian()) return;
  7431. #endif
  7432. set_current_to_destination();
  7433. }
  7434. #if ENABLED(ARC_SUPPORT)
  7435. /**
  7436. * Plan an arc in 2 dimensions
  7437. *
  7438. * The arc is approximated by generating many small linear segments.
  7439. * The length of each segment is configured in MM_PER_ARC_SEGMENT (Default 1mm)
  7440. * Arcs should only be made relatively large (over 5mm), as larger arcs with
  7441. * larger segments will tend to be more efficient. Your slicer should have
  7442. * options for G2/G3 arc generation. In future these options may be GCode tunable.
  7443. */
  7444. void plan_arc(
  7445. float logical[NUM_AXIS], // Destination position
  7446. float* offset, // Center of rotation relative to current_position
  7447. uint8_t clockwise // Clockwise?
  7448. ) {
  7449. float radius = HYPOT(offset[X_AXIS], offset[Y_AXIS]),
  7450. center_X = current_position[X_AXIS] + offset[X_AXIS],
  7451. center_Y = current_position[Y_AXIS] + offset[Y_AXIS],
  7452. linear_travel = logical[Z_AXIS] - current_position[Z_AXIS],
  7453. extruder_travel = logical[E_AXIS] - current_position[E_AXIS],
  7454. r_X = -offset[X_AXIS], // Radius vector from center to current location
  7455. r_Y = -offset[Y_AXIS],
  7456. rt_X = logical[X_AXIS] - center_X,
  7457. rt_Y = logical[Y_AXIS] - center_Y;
  7458. // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required.
  7459. float angular_travel = atan2(r_X * rt_Y - r_Y * rt_X, r_X * rt_X + r_Y * rt_Y);
  7460. if (angular_travel < 0) angular_travel += RADIANS(360);
  7461. if (clockwise) angular_travel -= RADIANS(360);
  7462. // Make a circle if the angular rotation is 0
  7463. if (angular_travel == 0 && current_position[X_AXIS] == logical[X_AXIS] && current_position[Y_AXIS] == logical[Y_AXIS])
  7464. angular_travel += RADIANS(360);
  7465. float mm_of_travel = HYPOT(angular_travel * radius, fabs(linear_travel));
  7466. if (mm_of_travel < 0.001) return;
  7467. uint16_t segments = floor(mm_of_travel / (MM_PER_ARC_SEGMENT));
  7468. if (segments == 0) segments = 1;
  7469. float theta_per_segment = angular_travel / segments;
  7470. float linear_per_segment = linear_travel / segments;
  7471. float extruder_per_segment = extruder_travel / segments;
  7472. /**
  7473. * Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
  7474. * and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
  7475. * r_T = [cos(phi) -sin(phi);
  7476. * sin(phi) cos(phi] * r ;
  7477. *
  7478. * For arc generation, the center of the circle is the axis of rotation and the radius vector is
  7479. * defined from the circle center to the initial position. Each line segment is formed by successive
  7480. * vector rotations. This requires only two cos() and sin() computations to form the rotation
  7481. * matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
  7482. * all double numbers are single precision on the Arduino. (True double precision will not have
  7483. * round off issues for CNC applications.) Single precision error can accumulate to be greater than
  7484. * tool precision in some cases. Therefore, arc path correction is implemented.
  7485. *
  7486. * Small angle approximation may be used to reduce computation overhead further. This approximation
  7487. * holds for everything, but very small circles and large MM_PER_ARC_SEGMENT values. In other words,
  7488. * theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
  7489. * to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
  7490. * numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
  7491. * issue for CNC machines with the single precision Arduino calculations.
  7492. *
  7493. * This approximation also allows plan_arc to immediately insert a line segment into the planner
  7494. * without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
  7495. * a correction, the planner should have caught up to the lag caused by the initial plan_arc overhead.
  7496. * This is important when there are successive arc motions.
  7497. */
  7498. // Vector rotation matrix values
  7499. float cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
  7500. float sin_T = theta_per_segment;
  7501. float arc_target[NUM_AXIS];
  7502. float sin_Ti, cos_Ti, r_new_Y;
  7503. uint16_t i;
  7504. int8_t count = 0;
  7505. // Initialize the linear axis
  7506. arc_target[Z_AXIS] = current_position[Z_AXIS];
  7507. // Initialize the extruder axis
  7508. arc_target[E_AXIS] = current_position[E_AXIS];
  7509. float fr_mm_s = MMS_SCALED(feedrate_mm_s);
  7510. millis_t next_idle_ms = millis() + 200UL;
  7511. for (i = 1; i < segments; i++) { // Iterate (segments-1) times
  7512. thermalManager.manage_heater();
  7513. millis_t now = millis();
  7514. if (ELAPSED(now, next_idle_ms)) {
  7515. next_idle_ms = now + 200UL;
  7516. idle();
  7517. }
  7518. if (++count < N_ARC_CORRECTION) {
  7519. // Apply vector rotation matrix to previous r_X / 1
  7520. r_new_Y = r_X * sin_T + r_Y * cos_T;
  7521. r_X = r_X * cos_T - r_Y * sin_T;
  7522. r_Y = r_new_Y;
  7523. }
  7524. else {
  7525. // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
  7526. // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
  7527. // To reduce stuttering, the sin and cos could be computed at different times.
  7528. // For now, compute both at the same time.
  7529. cos_Ti = cos(i * theta_per_segment);
  7530. sin_Ti = sin(i * theta_per_segment);
  7531. r_X = -offset[X_AXIS] * cos_Ti + offset[Y_AXIS] * sin_Ti;
  7532. r_Y = -offset[X_AXIS] * sin_Ti - offset[Y_AXIS] * cos_Ti;
  7533. count = 0;
  7534. }
  7535. // Update arc_target location
  7536. arc_target[X_AXIS] = center_X + r_X;
  7537. arc_target[Y_AXIS] = center_Y + r_Y;
  7538. arc_target[Z_AXIS] += linear_per_segment;
  7539. arc_target[E_AXIS] += extruder_per_segment;
  7540. clamp_to_software_endstops(arc_target);
  7541. #if IS_KINEMATIC
  7542. inverse_kinematics(arc_target);
  7543. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
  7544. #else
  7545. planner.buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], fr_mm_s, active_extruder);
  7546. #endif
  7547. }
  7548. // Ensure last segment arrives at target location.
  7549. #if IS_KINEMATIC
  7550. inverse_kinematics(logical);
  7551. planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
  7552. #else
  7553. planner.buffer_line(logical[X_AXIS], logical[Y_AXIS], logical[Z_AXIS], logical[E_AXIS], fr_mm_s, active_extruder);
  7554. #endif
  7555. // As far as the parser is concerned, the position is now == target. In reality the
  7556. // motion control system might still be processing the action and the real tool position
  7557. // in any intermediate location.
  7558. set_current_to_destination();
  7559. }
  7560. #endif
  7561. #if ENABLED(BEZIER_CURVE_SUPPORT)
  7562. void plan_cubic_move(const float offset[4]) {
  7563. cubic_b_spline(current_position, destination, offset, MMS_SCALED(feedrate_mm_s), active_extruder);
  7564. // As far as the parser is concerned, the position is now == destination. In reality the
  7565. // motion control system might still be processing the action and the real tool position
  7566. // in any intermediate location.
  7567. set_current_to_destination();
  7568. }
  7569. #endif // BEZIER_CURVE_SUPPORT
  7570. #if HAS_CONTROLLERFAN
  7571. void controllerFan() {
  7572. static millis_t lastMotorOn = 0; // Last time a motor was turned on
  7573. static millis_t nextMotorCheck = 0; // Last time the state was checked
  7574. millis_t ms = millis();
  7575. if (ELAPSED(ms, nextMotorCheck)) {
  7576. nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
  7577. if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || thermalManager.soft_pwm_bed > 0
  7578. || E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled...
  7579. #if E_STEPPERS > 1
  7580. || E1_ENABLE_READ == E_ENABLE_ON
  7581. #if HAS_X2_ENABLE
  7582. || X2_ENABLE_READ == X_ENABLE_ON
  7583. #endif
  7584. #if E_STEPPERS > 2
  7585. || E2_ENABLE_READ == E_ENABLE_ON
  7586. #if E_STEPPERS > 3
  7587. || E3_ENABLE_READ == E_ENABLE_ON
  7588. #endif
  7589. #endif
  7590. #endif
  7591. ) {
  7592. lastMotorOn = ms; //... set time to NOW so the fan will turn on
  7593. }
  7594. // Fan off if no steppers have been enabled for CONTROLLERFAN_SECS seconds
  7595. uint8_t speed = (!lastMotorOn || ELAPSED(ms, lastMotorOn + (CONTROLLERFAN_SECS) * 1000UL)) ? 0 : CONTROLLERFAN_SPEED;
  7596. // allows digital or PWM fan output to be used (see M42 handling)
  7597. digitalWrite(CONTROLLERFAN_PIN, speed);
  7598. analogWrite(CONTROLLERFAN_PIN, speed);
  7599. }
  7600. }
  7601. #endif // HAS_CONTROLLERFAN
  7602. #if ENABLED(MORGAN_SCARA)
  7603. /**
  7604. * Morgan SCARA Forward Kinematics. Results in cartes[].
  7605. * Maths and first version by QHARLEY.
  7606. * Integrated into Marlin and slightly restructured by Joachim Cerny.
  7607. */
  7608. void forward_kinematics_SCARA(const float &a, const float &b) {
  7609. float a_sin = sin(RADIANS(a)) * L1,
  7610. a_cos = cos(RADIANS(a)) * L1,
  7611. b_sin = sin(RADIANS(b)) * L2,
  7612. b_cos = cos(RADIANS(b)) * L2;
  7613. cartes[X_AXIS] = a_cos + b_cos + SCARA_OFFSET_X; //theta
  7614. cartes[Y_AXIS] = a_sin + b_sin + SCARA_OFFSET_Y; //theta+phi
  7615. /*
  7616. SERIAL_ECHOPAIR("SCARA FK Angle a=", a);
  7617. SERIAL_ECHOPAIR(" b=", b);
  7618. SERIAL_ECHOPAIR(" a_sin=", a_sin);
  7619. SERIAL_ECHOPAIR(" a_cos=", a_cos);
  7620. SERIAL_ECHOPAIR(" b_sin=", b_sin);
  7621. SERIAL_ECHOLNPAIR(" b_cos=", b_cos);
  7622. SERIAL_ECHOPAIR(" cartes[X_AXIS]=", cartes[X_AXIS]);
  7623. SERIAL_ECHOLNPAIR(" cartes[Y_AXIS]=", cartes[Y_AXIS]);
  7624. //*/
  7625. }
  7626. /**
  7627. * Morgan SCARA Inverse Kinematics. Results in delta[].
  7628. *
  7629. * See http://forums.reprap.org/read.php?185,283327
  7630. *
  7631. * Maths and first version by QHARLEY.
  7632. * Integrated into Marlin and slightly restructured by Joachim Cerny.
  7633. */
  7634. void inverse_kinematics(const float logical[XYZ]) {
  7635. static float C2, S2, SK1, SK2, THETA, PSI;
  7636. float sx = RAW_X_POSITION(logical[X_AXIS]) - SCARA_OFFSET_X, // Translate SCARA to standard X Y
  7637. sy = RAW_Y_POSITION(logical[Y_AXIS]) - SCARA_OFFSET_Y; // With scaling factor.
  7638. if (L1 == L2)
  7639. C2 = HYPOT2(sx, sy) / L1_2_2 - 1;
  7640. else
  7641. C2 = (HYPOT2(sx, sy) - (L1_2 + L2_2)) / (2.0 * L1 * L2);
  7642. S2 = sqrt(sq(C2) - 1);
  7643. // Unrotated Arm1 plus rotated Arm2 gives the distance from Center to End
  7644. SK1 = L1 + L2 * C2;
  7645. // Rotated Arm2 gives the distance from Arm1 to Arm2
  7646. SK2 = L2 * S2;
  7647. // Angle of Arm1 is the difference between Center-to-End angle and the Center-to-Elbow
  7648. THETA = atan2(SK1, SK2) - atan2(sx, sy);
  7649. // Angle of Arm2
  7650. PSI = atan2(S2, C2);
  7651. delta[A_AXIS] = DEGREES(THETA); // theta is support arm angle
  7652. delta[B_AXIS] = DEGREES(THETA + PSI); // equal to sub arm angle (inverted motor)
  7653. delta[C_AXIS] = logical[Z_AXIS];
  7654. /*
  7655. DEBUG_POS("SCARA IK", logical);
  7656. DEBUG_POS("SCARA IK", delta);
  7657. SERIAL_ECHOPAIR(" SCARA (x,y) ", sx);
  7658. SERIAL_ECHOPAIR(",", sy);
  7659. SERIAL_ECHOPAIR(" C2=", C2);
  7660. SERIAL_ECHOPAIR(" S2=", S2);
  7661. SERIAL_ECHOPAIR(" Theta=", THETA);
  7662. SERIAL_ECHOLNPAIR(" Phi=", PHI);
  7663. //*/
  7664. }
  7665. #endif // MORGAN_SCARA
  7666. #if ENABLED(TEMP_STAT_LEDS)
  7667. static bool red_led = false;
  7668. static millis_t next_status_led_update_ms = 0;
  7669. void handle_status_leds(void) {
  7670. if (ELAPSED(millis(), next_status_led_update_ms)) {
  7671. next_status_led_update_ms += 500; // Update every 0.5s
  7672. float max_temp = 0.0;
  7673. #if HAS_TEMP_BED
  7674. max_temp = MAX3(max_temp, thermalManager.degTargetBed(), thermalManager.degBed());
  7675. #endif
  7676. HOTEND_LOOP() {
  7677. max_temp = MAX3(max_temp, thermalManager.degHotend(e), thermalManager.degTargetHotend(e));
  7678. }
  7679. bool new_led = (max_temp > 55.0) ? true : (max_temp < 54.0) ? false : red_led;
  7680. if (new_led != red_led) {
  7681. red_led = new_led;
  7682. WRITE(STAT_LED_RED_PIN, new_led ? HIGH : LOW);
  7683. WRITE(STAT_LED_BLUE_PIN, new_led ? LOW : HIGH);
  7684. }
  7685. }
  7686. }
  7687. #endif
  7688. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  7689. void handle_filament_runout() {
  7690. if (!filament_ran_out) {
  7691. filament_ran_out = true;
  7692. enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
  7693. stepper.synchronize();
  7694. }
  7695. }
  7696. #endif // FILAMENT_RUNOUT_SENSOR
  7697. #if ENABLED(FAST_PWM_FAN)
  7698. void setPwmFrequency(uint8_t pin, int val) {
  7699. val &= 0x07;
  7700. switch (digitalPinToTimer(pin)) {
  7701. #if defined(TCCR0A)
  7702. case TIMER0A:
  7703. case TIMER0B:
  7704. // TCCR0B &= ~(_BV(CS00) | _BV(CS01) | _BV(CS02));
  7705. // TCCR0B |= val;
  7706. break;
  7707. #endif
  7708. #if defined(TCCR1A)
  7709. case TIMER1A:
  7710. case TIMER1B:
  7711. // TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  7712. // TCCR1B |= val;
  7713. break;
  7714. #endif
  7715. #if defined(TCCR2)
  7716. case TIMER2:
  7717. case TIMER2:
  7718. TCCR2 &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
  7719. TCCR2 |= val;
  7720. break;
  7721. #endif
  7722. #if defined(TCCR2A)
  7723. case TIMER2A:
  7724. case TIMER2B:
  7725. TCCR2B &= ~(_BV(CS20) | _BV(CS21) | _BV(CS22));
  7726. TCCR2B |= val;
  7727. break;
  7728. #endif
  7729. #if defined(TCCR3A)
  7730. case TIMER3A:
  7731. case TIMER3B:
  7732. case TIMER3C:
  7733. TCCR3B &= ~(_BV(CS30) | _BV(CS31) | _BV(CS32));
  7734. TCCR3B |= val;
  7735. break;
  7736. #endif
  7737. #if defined(TCCR4A)
  7738. case TIMER4A:
  7739. case TIMER4B:
  7740. case TIMER4C:
  7741. TCCR4B &= ~(_BV(CS40) | _BV(CS41) | _BV(CS42));
  7742. TCCR4B |= val;
  7743. break;
  7744. #endif
  7745. #if defined(TCCR5A)
  7746. case TIMER5A:
  7747. case TIMER5B:
  7748. case TIMER5C:
  7749. TCCR5B &= ~(_BV(CS50) | _BV(CS51) | _BV(CS52));
  7750. TCCR5B |= val;
  7751. break;
  7752. #endif
  7753. }
  7754. }
  7755. #endif // FAST_PWM_FAN
  7756. float calculate_volumetric_multiplier(float diameter) {
  7757. if (!volumetric_enabled || diameter == 0) return 1.0;
  7758. float d2 = diameter * 0.5;
  7759. return 1.0 / (M_PI * d2 * d2);
  7760. }
  7761. void calculate_volumetric_multipliers() {
  7762. for (uint8_t i = 0; i < COUNT(filament_size); i++)
  7763. volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
  7764. }
  7765. void enable_all_steppers() {
  7766. enable_x();
  7767. enable_y();
  7768. enable_z();
  7769. enable_e0();
  7770. enable_e1();
  7771. enable_e2();
  7772. enable_e3();
  7773. }
  7774. void disable_all_steppers() {
  7775. disable_x();
  7776. disable_y();
  7777. disable_z();
  7778. disable_e0();
  7779. disable_e1();
  7780. disable_e2();
  7781. disable_e3();
  7782. }
  7783. /**
  7784. * Manage several activities:
  7785. * - Check for Filament Runout
  7786. * - Keep the command buffer full
  7787. * - Check for maximum inactive time between commands
  7788. * - Check for maximum inactive time between stepper commands
  7789. * - Check if pin CHDK needs to go LOW
  7790. * - Check for KILL button held down
  7791. * - Check for HOME button held down
  7792. * - Check if cooling fan needs to be switched on
  7793. * - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT)
  7794. */
  7795. void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
  7796. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  7797. if ((IS_SD_PRINTING || print_job_timer.isRunning()) && !(READ(FIL_RUNOUT_PIN) ^ FIL_RUNOUT_INVERTING))
  7798. handle_filament_runout();
  7799. #endif
  7800. if (commands_in_queue < BUFSIZE) get_available_commands();
  7801. millis_t ms = millis();
  7802. if (max_inactive_time && ELAPSED(ms, previous_cmd_ms + max_inactive_time)) kill(PSTR(MSG_KILLED));
  7803. if (stepper_inactive_time && ELAPSED(ms, previous_cmd_ms + stepper_inactive_time)
  7804. && !ignore_stepper_queue && !planner.blocks_queued()) {
  7805. #if ENABLED(DISABLE_INACTIVE_X)
  7806. disable_x();
  7807. #endif
  7808. #if ENABLED(DISABLE_INACTIVE_Y)
  7809. disable_y();
  7810. #endif
  7811. #if ENABLED(DISABLE_INACTIVE_Z)
  7812. disable_z();
  7813. #endif
  7814. #if ENABLED(DISABLE_INACTIVE_E)
  7815. disable_e0();
  7816. disable_e1();
  7817. disable_e2();
  7818. disable_e3();
  7819. #endif
  7820. }
  7821. #ifdef CHDK // Check if pin should be set to LOW after M240 set it to HIGH
  7822. if (chdkActive && PENDING(ms, chdkHigh + CHDK_DELAY)) {
  7823. chdkActive = false;
  7824. WRITE(CHDK, LOW);
  7825. }
  7826. #endif
  7827. #if HAS_KILL
  7828. // Check if the kill button was pressed and wait just in case it was an accidental
  7829. // key kill key press
  7830. // -------------------------------------------------------------------------------
  7831. static int killCount = 0; // make the inactivity button a bit less responsive
  7832. const int KILL_DELAY = 750;
  7833. if (!READ(KILL_PIN))
  7834. killCount++;
  7835. else if (killCount > 0)
  7836. killCount--;
  7837. // Exceeded threshold and we can confirm that it was not accidental
  7838. // KILL the machine
  7839. // ----------------------------------------------------------------
  7840. if (killCount >= KILL_DELAY) kill(PSTR(MSG_KILLED));
  7841. #endif
  7842. #if HAS_HOME
  7843. // Check to see if we have to home, use poor man's debouncer
  7844. // ---------------------------------------------------------
  7845. static int homeDebounceCount = 0; // poor man's debouncing count
  7846. const int HOME_DEBOUNCE_DELAY = 2500;
  7847. if (!READ(HOME_PIN)) {
  7848. if (!homeDebounceCount) {
  7849. enqueue_and_echo_commands_P(PSTR("G28"));
  7850. LCD_MESSAGEPGM(MSG_AUTO_HOME);
  7851. }
  7852. if (homeDebounceCount < HOME_DEBOUNCE_DELAY)
  7853. homeDebounceCount++;
  7854. else
  7855. homeDebounceCount = 0;
  7856. }
  7857. #endif
  7858. #if HAS_CONTROLLERFAN
  7859. controllerFan(); // Check if fan should be turned on to cool stepper drivers down
  7860. #endif
  7861. #if ENABLED(EXTRUDER_RUNOUT_PREVENT)
  7862. if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL)
  7863. && thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
  7864. bool oldstatus;
  7865. #if ENABLED(SWITCHING_EXTRUDER)
  7866. oldstatus = E0_ENABLE_READ;
  7867. enable_e0();
  7868. #else // !SWITCHING_EXTRUDER
  7869. switch (active_extruder) {
  7870. case 0:
  7871. oldstatus = E0_ENABLE_READ;
  7872. enable_e0();
  7873. break;
  7874. #if E_STEPPERS > 1
  7875. case 1:
  7876. oldstatus = E1_ENABLE_READ;
  7877. enable_e1();
  7878. break;
  7879. #if E_STEPPERS > 2
  7880. case 2:
  7881. oldstatus = E2_ENABLE_READ;
  7882. enable_e2();
  7883. break;
  7884. #if E_STEPPERS > 3
  7885. case 3:
  7886. oldstatus = E3_ENABLE_READ;
  7887. enable_e3();
  7888. break;
  7889. #endif
  7890. #endif
  7891. #endif
  7892. }
  7893. #endif // !SWITCHING_EXTRUDER
  7894. previous_cmd_ms = ms; // refresh_cmd_timeout()
  7895. planner.buffer_line(
  7896. current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
  7897. current_position[E_AXIS] + EXTRUDER_RUNOUT_EXTRUDE,
  7898. MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED), active_extruder
  7899. );
  7900. stepper.synchronize();
  7901. planner.set_e_position_mm(current_position[E_AXIS]);
  7902. #if ENABLED(SWITCHING_EXTRUDER)
  7903. E0_ENABLE_WRITE(oldstatus);
  7904. #else
  7905. switch (active_extruder) {
  7906. case 0:
  7907. E0_ENABLE_WRITE(oldstatus);
  7908. break;
  7909. #if E_STEPPERS > 1
  7910. case 1:
  7911. E1_ENABLE_WRITE(oldstatus);
  7912. break;
  7913. #if E_STEPPERS > 2
  7914. case 2:
  7915. E2_ENABLE_WRITE(oldstatus);
  7916. break;
  7917. #if E_STEPPERS > 3
  7918. case 3:
  7919. E3_ENABLE_WRITE(oldstatus);
  7920. break;
  7921. #endif
  7922. #endif
  7923. #endif
  7924. }
  7925. #endif // !SWITCHING_EXTRUDER
  7926. }
  7927. #endif // EXTRUDER_RUNOUT_PREVENT
  7928. #if ENABLED(DUAL_X_CARRIAGE)
  7929. // handle delayed move timeout
  7930. if (delayed_move_time && ELAPSED(ms, delayed_move_time + 1000UL) && IsRunning()) {
  7931. // travel moves have been received so enact them
  7932. delayed_move_time = 0xFFFFFFFFUL; // force moves to be done
  7933. set_destination_to_current();
  7934. prepare_move_to_destination();
  7935. }
  7936. #endif
  7937. #if ENABLED(TEMP_STAT_LEDS)
  7938. handle_status_leds();
  7939. #endif
  7940. planner.check_axes_activity();
  7941. }
  7942. /**
  7943. * Standard idle routine keeps the machine alive
  7944. */
  7945. void idle(
  7946. #if ENABLED(FILAMENT_CHANGE_FEATURE)
  7947. bool no_stepper_sleep/*=false*/
  7948. #endif
  7949. ) {
  7950. lcd_update();
  7951. host_keepalive();
  7952. manage_inactivity(
  7953. #if ENABLED(FILAMENT_CHANGE_FEATURE)
  7954. no_stepper_sleep
  7955. #endif
  7956. );
  7957. thermalManager.manage_heater();
  7958. #if ENABLED(PRINTCOUNTER)
  7959. print_job_timer.tick();
  7960. #endif
  7961. #if HAS_BUZZER && PIN_EXISTS(BEEPER)
  7962. buzzer.tick();
  7963. #endif
  7964. }
  7965. /**
  7966. * Kill all activity and lock the machine.
  7967. * After this the machine will need to be reset.
  7968. */
  7969. void kill(const char* lcd_msg) {
  7970. SERIAL_ERROR_START;
  7971. SERIAL_ERRORLNPGM(MSG_ERR_KILLED);
  7972. #if ENABLED(ULTRA_LCD)
  7973. kill_screen(lcd_msg);
  7974. #else
  7975. UNUSED(lcd_msg);
  7976. #endif
  7977. delay(500); // Wait a short time
  7978. cli(); // Stop interrupts
  7979. thermalManager.disable_all_heaters();
  7980. disable_all_steppers();
  7981. #if HAS_POWER_SWITCH
  7982. pinMode(PS_ON_PIN, INPUT);
  7983. #endif
  7984. suicide();
  7985. while (1) {
  7986. #if ENABLED(USE_WATCHDOG)
  7987. watchdog_reset();
  7988. #endif
  7989. } // Wait for reset
  7990. }
  7991. /**
  7992. * Turn off heaters and stop the print in progress
  7993. * After a stop the machine may be resumed with M999
  7994. */
  7995. void stop() {
  7996. thermalManager.disable_all_heaters();
  7997. if (IsRunning()) {
  7998. Running = false;
  7999. Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart
  8000. SERIAL_ERROR_START;
  8001. SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
  8002. LCD_MESSAGEPGM(MSG_STOPPED);
  8003. }
  8004. }
  8005. /**
  8006. * Marlin entry-point: Set up before the program loop
  8007. * - Set up the kill pin, filament runout, power hold
  8008. * - Start the serial port
  8009. * - Print startup messages and diagnostics
  8010. * - Get EEPROM or default settings
  8011. * - Initialize managers for:
  8012. * • temperature
  8013. * • planner
  8014. * • watchdog
  8015. * • stepper
  8016. * • photo pin
  8017. * • servos
  8018. * • LCD controller
  8019. * • Digipot I2C
  8020. * • Z probe sled
  8021. * • status LEDs
  8022. */
  8023. void setup() {
  8024. #ifdef DISABLE_JTAG
  8025. // Disable JTAG on AT90USB chips to free up pins for IO
  8026. MCUCR = 0x80;
  8027. MCUCR = 0x80;
  8028. #endif
  8029. #if ENABLED(FILAMENT_RUNOUT_SENSOR)
  8030. setup_filrunoutpin();
  8031. #endif
  8032. setup_killpin();
  8033. setup_powerhold();
  8034. #if HAS_STEPPER_RESET
  8035. disableStepperDrivers();
  8036. #endif
  8037. MYSERIAL.begin(BAUDRATE);
  8038. SERIAL_PROTOCOLLNPGM("start");
  8039. SERIAL_ECHO_START;
  8040. // Check startup - does nothing if bootloader sets MCUSR to 0
  8041. byte mcu = MCUSR;
  8042. if (mcu & 1) SERIAL_ECHOLNPGM(MSG_POWERUP);
  8043. if (mcu & 2) SERIAL_ECHOLNPGM(MSG_EXTERNAL_RESET);
  8044. if (mcu & 4) SERIAL_ECHOLNPGM(MSG_BROWNOUT_RESET);
  8045. if (mcu & 8) SERIAL_ECHOLNPGM(MSG_WATCHDOG_RESET);
  8046. if (mcu & 32) SERIAL_ECHOLNPGM(MSG_SOFTWARE_RESET);
  8047. MCUSR = 0;
  8048. SERIAL_ECHOPGM(MSG_MARLIN);
  8049. SERIAL_CHAR(' ');
  8050. SERIAL_ECHOLNPGM(SHORT_BUILD_VERSION);
  8051. SERIAL_EOL;
  8052. #if defined(STRING_DISTRIBUTION_DATE) && defined(STRING_CONFIG_H_AUTHOR)
  8053. SERIAL_ECHO_START;
  8054. SERIAL_ECHOPGM(MSG_CONFIGURATION_VER);
  8055. SERIAL_ECHOPGM(STRING_DISTRIBUTION_DATE);
  8056. SERIAL_ECHOLNPGM(MSG_AUTHOR STRING_CONFIG_H_AUTHOR);
  8057. SERIAL_ECHOLNPGM("Compiled: " __DATE__);
  8058. #endif
  8059. SERIAL_ECHO_START;
  8060. SERIAL_ECHOPAIR(MSG_FREE_MEMORY, freeMemory());
  8061. SERIAL_ECHOLNPAIR(MSG_PLANNER_BUFFER_BYTES, (int)sizeof(block_t)*BLOCK_BUFFER_SIZE);
  8062. // Send "ok" after commands by default
  8063. for (int8_t i = 0; i < BUFSIZE; i++) send_ok[i] = true;
  8064. // Load data from EEPROM if available (or use defaults)
  8065. // This also updates variables in the planner, elsewhere
  8066. Config_RetrieveSettings();
  8067. // Initialize current position based on home_offset
  8068. memcpy(current_position, home_offset, sizeof(home_offset));
  8069. // Vital to init stepper/planner equivalent for current_position
  8070. SYNC_PLAN_POSITION_KINEMATIC();
  8071. thermalManager.init(); // Initialize temperature loop
  8072. #if ENABLED(USE_WATCHDOG)
  8073. watchdog_init();
  8074. #endif
  8075. stepper.init(); // Initialize stepper, this enables interrupts!
  8076. setup_photpin();
  8077. servo_init();
  8078. #if HAS_BED_PROBE
  8079. endstops.enable_z_probe(false);
  8080. #endif
  8081. #if HAS_CONTROLLERFAN
  8082. SET_OUTPUT(CONTROLLERFAN_PIN); //Set pin used for driver cooling fan
  8083. #endif
  8084. #if HAS_STEPPER_RESET
  8085. enableStepperDrivers();
  8086. #endif
  8087. #if ENABLED(DIGIPOT_I2C)
  8088. digipot_i2c_init();
  8089. #endif
  8090. #if ENABLED(DAC_STEPPER_CURRENT)
  8091. dac_init();
  8092. #endif
  8093. #if ENABLED(Z_PROBE_SLED) && PIN_EXISTS(SLED)
  8094. OUT_WRITE(SLED_PIN, LOW); // turn it off
  8095. #endif // Z_PROBE_SLED
  8096. setup_homepin();
  8097. #if PIN_EXISTS(STAT_LED_RED)
  8098. OUT_WRITE(STAT_LED_RED_PIN, LOW); // turn it off
  8099. #endif
  8100. #if PIN_EXISTS(STAT_LED_BLUE)
  8101. OUT_WRITE(STAT_LED_BLUE_PIN, LOW); // turn it off
  8102. #endif
  8103. lcd_init();
  8104. #if ENABLED(SHOW_BOOTSCREEN)
  8105. #if ENABLED(DOGLCD)
  8106. safe_delay(BOOTSCREEN_TIMEOUT);
  8107. #elif ENABLED(ULTRA_LCD)
  8108. bootscreen();
  8109. lcd_init();
  8110. #endif
  8111. #endif
  8112. #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
  8113. // Initialize mixing to 100% color 1
  8114. for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
  8115. mixing_factor[i] = (i == 0) ? 1 : 0;
  8116. for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS; t++)
  8117. for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
  8118. mixing_virtual_tool_mix[t][i] = mixing_factor[i];
  8119. #endif
  8120. #if ENABLED(EXPERIMENTAL_I2CBUS) && I2C_SLAVE_ADDRESS > 0
  8121. i2c.onReceive(i2c_on_receive);
  8122. i2c.onRequest(i2c_on_request);
  8123. #endif
  8124. }
  8125. /**
  8126. * The main Marlin program loop
  8127. *
  8128. * - Save or log commands to SD
  8129. * - Process available commands (if not saving)
  8130. * - Call heater manager
  8131. * - Call inactivity manager
  8132. * - Call endstop manager
  8133. * - Call LCD update
  8134. */
  8135. void loop() {
  8136. if (commands_in_queue < BUFSIZE) get_available_commands();
  8137. #if ENABLED(SDSUPPORT)
  8138. card.checkautostart(false);
  8139. #endif
  8140. if (commands_in_queue) {
  8141. #if ENABLED(SDSUPPORT)
  8142. if (card.saving) {
  8143. char* command = command_queue[cmd_queue_index_r];
  8144. if (strstr_P(command, PSTR("M29"))) {
  8145. // M29 closes the file
  8146. card.closefile();
  8147. SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED);
  8148. ok_to_send();
  8149. }
  8150. else {
  8151. // Write the string from the read buffer to SD
  8152. card.write_command(command);
  8153. if (card.logging)
  8154. process_next_command(); // The card is saving because it's logging
  8155. else
  8156. ok_to_send();
  8157. }
  8158. }
  8159. else
  8160. process_next_command();
  8161. #else
  8162. process_next_command();
  8163. #endif // SDSUPPORT
  8164. // The queue may be reset by a command handler or by code invoked by idle() within a handler
  8165. if (commands_in_queue) {
  8166. --commands_in_queue;
  8167. cmd_queue_index_r = (cmd_queue_index_r + 1) % BUFSIZE;
  8168. }
  8169. }
  8170. endstops.report_state();
  8171. idle();
  8172. }