深入Marlin韌體

2021-09-28 21:49:50 字數 3119 閱讀 9532

marlin是一款開源3d印表機韌體,相信自己diy過印表機的人對這個韌體都不會陌生吧!目前市面上的桌面級3d印表機也都或多或少會有他的影子。marlin的強大之處在於支援多種不同結構的3d印表機(如:xyz直角結構,corexy、scara、三角洲等結構),支援多種硬體電路板,支援多種語言還附加了一些額外功能,如:自動調平等。正是這些強大的功能讓marlin韌體的源**看起來就比較難懂了。

最初接觸3d列印是在大學的時候了,當時一直想自己做一台自己的3d印表機。後面接觸到了marlin韌體和ramps控制板,熟悉過之後便有了將它移植到stm32的想法。之後便開始了對marlin韌體的漫漫學習之路,當時網上關於marlin的資料還很少,不過就那些很少的資料中還是給到了我很大的幫助,我還加了很多3d印表機diy的群向群中的各位大蝦請教不懂得問題。後面到要做畢設的時候,我就直接找到畢設的老師商量,最終確定讓我畢設做3d印表機的題目。最後經過風雨(查閱資料,各種請教,移植的**,繪製的pcb,搭建機械結構)之後終於見到了彩虹(印表機原型機成功問世)。對於螢幕選單部分當時也想直接移植marlin韌體的螢幕選單的結構,當時看到各種巨集定義,直接當場崩潰。只能另尋他路參考了一篇12864選單設計的帖子,參照這個選單結構完成了印表機的選單設計。但當時遇到乙個問題感覺用這個結構解決不是很好—sd卡中的檔案的顯示(我不知道sd卡中有多少個檔案,如何提前確定當前選單的條目數呢?)。

本想這樣就可以了,我又突發奇想—是不是可以將marlin韌體拆分成各個元件呢,既可以學習其中涉及到的演算法知識又可以為後續寫其他**預留基礎何樂而不為呢?

以下部分便是marlin韌體選單結構的核心**了。

/* helper macros for menus */

#define start_menu() do else\

}\if (wasclicked && (encoderposition / encoder_steps_per_menu_item) == _menuitemnr) \

}\_menuitemnr++;\

} while(0)

#define menu_item_dummy() do while(0)

#define menu_item_edit(type, label, args...) menu_item(setting_edit_ ## type, label, pstr(label) , ## args )

#define menu_item_edit_callback(type, label, args...) menu_item(setting_edit_callback_ ## type, label, pstr(label) , ## args )

#define end_menu() \

if (encoderposition / encoder_steps_per_menu_item >= _menuitemnr) encoderposition = _menuitemnr * encoder_steps_per_menu_item - 1; \

if ((uint8_t)(encoderposition / encoder_steps_per_menu_item) >= currentmenuviewoffset + lcd_height) \

} } while(0)

程式中涉及到的變數的含義:

encoderposition //記錄了編碼器位置的變數(如:編碼器左轉編碼器位置加一,編碼器右轉編碼器位置減一)

encoder_steps_per_menu_item //編碼器轉幾個脈衝對應於選單乙個條目

encoderposition / encoder_steps_per_menu_item //相當於記錄了按鍵的位置

currentmenuviewoffset //螢幕頂行顯示的條目對應於當前所有選單條目的的偏移量(選單開始顯示的頂行)

_linenr //當前需要繪製和處理的選單條目

_menuitemnr //每個選單中條目的索引

_drawlinenr //lcd顯示行的索引(如:0-3)

wasclicked //記錄了確認按鍵時候按下

lcddrawupdate //lcd繪製更新的標誌位

通過start_menu的巨集函式開始建立選單,通過menu_item的巨集函式向該選單中增加條目,通過end_menj的巨集函式結束當前選單的建立。menu_item的巨集函式需要呼叫以下兩個函式為為選單的條目生成繪製和處理**。

lcd_implementation_drawmenu_[type]

(sel,row,label,arg...

)menu_action_[type]

(arg...

)

這意味著我們每建立乙個條目就要維護這樣的兩個函式。通過對選單型別進行劃分可以一定程度上減少一部分該工作。對於marlin韌體選單的型別大致分為以下幾類:子選單、編輯選單、返回選單、g**選單、功能選單。

對於marlin的選單部分基本理解了上面的選單結構整個選單的框架就已經清晰明了了。對於該選單結構移植到stm32的測試**可以移步到:具體的測試螢幕用的是lcd12864(st7920)。

對於自動調平功能上述框圖中列出的是最新版的marlin韌體所支援的調平方式。自動調平功能的本質原理並不複雜,複雜的是整個調平過正中的流程,這流程是為了確保整個調平過程中的安全。這裡先簡單對以下兩種調平方式簡單分析,這兩種調平方式要卻保列印床是乙個平整的平面。

我們根據之前學過的只是,很容易知道3個不在同一直線上的點可以確定乙個平面,該方式正是利用的這個原理。

首先利用探針探測3個不在同一直線3個點的座標。

求取平面的法向量

計算該平面的方向量與理論平面法向量之間的旋轉矩陣

以後每次列印的目標點都通過該旋轉矩陣變換便可以變換為相對於當前平面的相對位置。

在高中大家應該都會學過線性回歸分析的課程,中間用到了最小二乘法的知識,這裡其實利用的也是這方面的原理。只不過我們當時使用一系列的平面點來擬合直線,而我們現在是利用一系列的空間點來擬合平面。

探測一系列的點

通過最小二乘法的優化演算法求取該平面的法向量

計算該平面的方向量與理論平面法向量之間的旋轉矩陣

以後每次列印的目標點都通過該旋轉矩陣變換便可以變換為相對於當前平面的相對位置。

對於調平背後的演算法而言,如果不深入研究,可以將它視為乙個黑箱,只需知道輸入和輸出即可。

Marlin韌體學習總結(一)

接觸過3d列印也有一段時間了,一直沒有將學到的知識以文字的形式記錄下來。現在也沒有太多時間繼續玩這個了,因此想慢慢把之前所接觸到所學到的知識通過文字的形式記錄一下,也分享給那些感興趣的人。既然是開篇我們先了解一下marlin韌體的結構吧!這部分的知識來自於 marlin韌體詳解 上面這個思維導圖從功...

Marlin韌體 G Code 命令解析

命令意義引數示例備註 g0 g1 線性移動 e e 軸的相對或絕對座標,描述進料絲的位置 f 在起點和終點之間移動的最大速率 x y z x y z 軸的相對或絕對座標 g1 f1500 設定進料速度為1500mm m g1 x50 y25.3 e22.4 擠出時移動 1 預設是以公釐為單位,可以通...

龍印 marlin移植雜記

本文為在用龍芯1c做3d印表機過程中的筆記。龍芯1c做的3d印表機簡稱 龍印 開始以為是沒有加標頭檔案 include 後來加了,還是提示這個錯誤,找了很久沒發現原因,最後在 man lround 中看到了compile with std c99 link with lm 加上 std c99後試了...