對(duì)于入行一年的我來(lái)說(shuō),桌面級(jí)FDM打印機(jī)很多功能細(xì)節(jié),我還沒(méi)能仔細(xì)了解:藏在固件代碼背后的信息內(nèi)容,我也遠(yuǎn)沒(méi)有完全消化。這正說(shuō)明一個(gè)簡(jiǎn)單的道理:消化一段代碼的最有效方法是對(duì)其移植或者重寫(xiě)。換言之,僅僅是走馬觀花的瀏覽一遍,除非自己曾經(jīng)編寫(xiě)過(guò)類似程序,很難能透徹的領(lǐng)會(huì)固件代碼的精髓。特別是對(duì)Marlin這個(gè)數(shù)百名(可能不準(zhǔn)確)開(kāi)源工程師貢獻(xiàn)和維護(hù)的大型固件項(xiàng)目。
創(chuàng)新互聯(lián)公司是一家專注于成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)與策劃設(shè)計(jì),沁縣網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:沁縣等地區(qū)。沁縣做網(wǎng)站價(jià)格咨詢:028-86922220Marlin的步進(jìn)電機(jī)驅(qū)動(dòng)子系統(tǒng),是由中斷響應(yīng)函數(shù)實(shí)現(xiàn)的。如果是恒定速度的步進(jìn)電機(jī)驅(qū)動(dòng),實(shí)現(xiàn)就和這句話一樣簡(jiǎn)單。不過(guò)對(duì)于3D打印機(jī)系統(tǒng),x,y軸的運(yùn)動(dòng)往往速度變化非常頻繁:不僅在每次更新位置的速度不同,而且每一段位移的速度也需要經(jīng)歷加速,恒速和減速階段。這是由機(jī)械系統(tǒng)的慣性特征決定的:如果不同動(dòng)作之間的速度銜接不好,會(huì)對(duì)電路系統(tǒng)造成強(qiáng)大的電流沖擊。特別是3D打印過(guò)程,這種速度的變化每次打印任務(wù)都數(shù)以萬(wàn)計(jì),這就意味著電路壽命將大打折扣。
Marlin系統(tǒng)的速度銜接,基于leib Ramp Algorithm[1],這是一個(gè)支撐步進(jìn)電機(jī)速度和控制器計(jì)數(shù)器頻率關(guān)系的算法理論,由IBM的工程師于1994年發(fā)表并于2004年在控制器內(nèi)實(shí)現(xiàn)。這里算法實(shí)現(xiàn)的關(guān)鍵在于路徑規(guī)劃器(planner)。路徑規(guī)劃器的設(shè)計(jì)意味著,程序在執(zhí)行步進(jìn)電機(jī)的動(dòng)作之前,就已經(jīng)計(jì)算好了整個(gè)過(guò)程的速度曲線。后面就只是Stepper模塊忠實(shí)地執(zhí)行。
在機(jī)器層面,這樣的設(shè)計(jì)減少了中斷響應(yīng)函數(shù)中的運(yùn)算量,這對(duì)于單片機(jī)來(lái)說(shuō)非常友好。同時(shí)3D打印機(jī)的機(jī)械運(yùn)動(dòng)相比控制器的16M主頻來(lái)說(shuō)要慢很多,路徑規(guī)劃器相比直接驅(qū)動(dòng),增加了一個(gè)運(yùn)動(dòng)緩存。這樣就能夠有效的利用控制器的高頻率,里面蘊(yùn)藏著“空間換取時(shí)間”的思想。
在代碼層面,planner的本質(zhì)在于對(duì)于一個(gè)FIFO的管理。使用C++的結(jié)構(gòu)體指針數(shù)據(jù)結(jié)構(gòu)能夠非常優(yōu)雅的實(shí)現(xiàn)這個(gè)緩存的創(chuàng)建和管理:planner.h:
typedef struct { // Fields used by the bresenham algorithm for tracing the line long steps_x, steps_y, steps_z, steps_e; // Step count along each axis unsigned long step_event_count; // The number of step events required to complete this block long accelerate_until; // The index of the step event on which to stop acceleration long decelerate_after; // The index of the step event on which to start decelerating long acceleration_rate; // The acceleration rate used for acceleration calculation unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) float nominal_speed; // The nominal speed for this block in mm/sec float entry_speed; // Entry speed at previous-current junction in mm/sec float max_entry_speed; // Maximum allowable junction entry speed in mm/sec float millimeters; // The total travel of this block in mm float acceleration; // acceleration mm/sec^2 unsigned char recalculate_flag; // Planner flag to recalculate trapezoids on entry junction unsigned char nominal_length_flag; // Planner flag for nominal speed always reached // Settings for the trapezoid generator unsigned long nominal_rate; // The nominal step rate for this block in step_events/sec unsigned long initial_rate; // The jerk-adjusted step rate at start of block unsigned long final_rate; // The minimal rate at exit unsigned long acceleration_st; // acceleration steps/sec^2 unsigned long fan_speed; #ifdef BARICUDA unsigned long valve_pressure; unsigned long e_to_p_pressure; #endif volatile char busy; } block_t; block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions volatile unsigned char block_buffer_head; // Index of the next block to be pushed volatile unsigned char block_buffer_tail;
volatile 關(guān)鍵字確保了隊(duì)列頭和隊(duì)列尾被不同函數(shù)訪問(wèn)過(guò)程中,編譯器不會(huì)因?yàn)閮?yōu)化和丟失更改行為。block_t類型的指針可以方便的方位結(jié)構(gòu)體內(nèi)任何元素。在后面的planner規(guī)劃動(dòng)作plan_buffer_line()中,代碼可以用非常優(yōu)雅的結(jié)構(gòu)體指針來(lái)完成。
每當(dāng)3D打印機(jī)解析到位移指令的時(shí)候,plan_buffer_line()函數(shù)就被調(diào)用。在里面新的block_t首先被創(chuàng)建,并且排入隊(duì)列的隊(duì)尾;然后執(zhí)行calculate_trapezoid_for_block(),計(jì)算新的block_t的關(guān)鍵速度節(jié)點(diǎn)及其對(duì)應(yīng)的step數(shù)目;接著更新隊(duì)列里面所有block_t的連接速度:之前隊(duì)尾的block_t的收尾速度和相關(guān)速度節(jié)點(diǎn)會(huì)被更新。最后調(diào)用st_wake_up()保證stepper執(zhí)行的中斷打開(kāi)。
而在%steppper中,ISR函數(shù)負(fù)責(zé)在主循環(huán)之外,執(zhí)行隊(duì)列里可能存在的所有block_t。在ISR中,首先由plan_get_current_block()讀取隊(duì)列首的block_t,然后按照結(jié)構(gòu)成員的step數(shù),調(diào)用STEP_ADD和STEP_IF_COUNTER兩個(gè)宏來(lái)執(zhí)行x,y,z三軸的運(yùn)動(dòng)。ISR每執(zhí)行一次,三路各發(fā)出一個(gè)脈沖,并通過(guò)lamp ramp算法更新,根據(jù)下一個(gè)速度值來(lái)更新OCR1A寄存器來(lái)設(shè)定下一次中斷響應(yīng)的周期。
整個(gè)軟件C++實(shí)現(xiàn)妙至毫巔。建議大家在win環(huán)境使用eclipse來(lái)查看Cpp工程。eclipse對(duì)條件預(yù)編譯的支持非常完美,#if def能夠準(zhǔn)確顯隱,可讀性非常好(見(jiàn)下圖)。全局查詢,go to define等功能也很完備。
另外,eclipse有豐富的快捷鍵支持看代碼:用ctrl+shift+G就能查到變量的引用;F12就能查到變量的定義。Alt+左鍵 /右鍵回到之前的鼠標(biāo)位置和之后的鼠標(biāo)位置;用CTRL+SHIFT+P就能尋找括號(hào)的另外一半。
附Marlin項(xiàng)目
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。