elsa in mac

Absolute Extrusion vs. Relative Extrusion 본문

3D 프린터/3D 프린터 관련 정보

Absolute Extrusion vs. Relative Extrusion

elsa in mac 2018. 12. 24. 19:29

3D 프린터 Extruder

내일이 2018년 크리스마스 이네요.. 메리 크리스마스~ ^^

크리스마스 이브 포스팅치고는 썩 어울리지 않지만.. 이번 포스트는 3D프린터의 Absolute Extrusion 과 Relative Extrusion에 관해 애기를 해 볼까 합니다. 

크리스마스 이미지

Extrusion은 필라멘트 압출을 의미하는 것인데, Absolute와 Relative는 적절히 뭐라고 해석을 해야 할 지 처음부터 좀 난감하네요.. 사실은 이것은 좌표계와 관련된거라 위치라고 해석을 하면 되지만, Extruder(압출기)의 기능이 좀 특이해서 말이죠... 암튼, 굳이 번역을 하면 Absolute Extrusion은 절대위치 압출, Relative Extrusion은 상대위치 압출 정도의 의미가 적당할 것 같습니다. ^^

음.. 비교적 최근들어 Cura, Simplify3D, Slic3r, Kissslicer등 거의 대 부분의 Slicer들이 Relative Extrusion을 지원하기 시작했습니다. 새롭게 지원을 하기 시작했다는 것은 예전의 방식과 비교해 뭔가 더 좋은 잇점이 있기 때문일 텐데요.. 이번 포스트에서는 그것이 무엇인지를 알아보는 것입니다. 

3D프린팅을 하는 각각의 출력 단위.. 쉽게 말해 선 긋기.. 이것을 우리는 Segment(세그먼트)라고 부릅니다. 즉, 3D 프린팅을 한다는 것은 하나의 단일 동작을 정의한 Segment를 순차적으로 연 이어 실행하는 것이고, 따라서 이를 Segment Sequence(세그먼트 시퀀스)라고 표현 할 수 있을 것 같은데요.. Slicer(슬라이서) 앱를 통해 생성한 Gcode(G코드)가 바로 Segment Sequence인 셈 입니다. 각 Segment에는 Hotend의 새로운 좌표(X/Y/Z)와 함께, 현재 Segment에서 얼마 만큼 필라멘트를 압출할 것인가가 정의되어 있습니다. 

이와 관련하여 전통적인 방법은 Absolute Extrusion 방식 입니다.  즉, 프린팅을 시작해서 필라멘트 압출을 시작하기 전 상태를 압출량 0mm 라고 정의하고, 이 후, 각 Segment에서 출력에 필요한 압출량을 계속 누적하여 표시 하는 방법입니다. 이론적으로는, 맨 마지막 Segment에는 3D모델을 출력하는데 압출한 총 필라멘트 양이 표시가 될 것입니다.

반대로, Relative Extrusion은 각 Segment가 압출 0mm로 부터 다시 시작(reset)을 하는 개념입니다. 즉, 각각의 Segment에서 정확히 출력을 위해 요구되는 필요한 필라멘트 양만 정의하는 것입니다.  정의 만으로는 감이 잘 안오니 예를 들어 보겠습니다. 

아래 두 줄의 Segment가 정의되어 있습니다.

G1 X100 Y100 E10
G1 X110 Y100 E12

만일 Absolute Extrusion 모드라면, 위의 코드는 아래와 같이 해석이 됩니다.
X100 Y100 위치로 이동하면서 현재까지 총 10mm 압출.
X110 Y100 위치로 이동하면서 현재까지 총 12mm 압출.

반대로, Relative Extrusion 모드라면 위의 코드는 아래와 같이 해석이 됩니다.
X100 Y100 위치로 이동하면서 새롭게 10mm를 압출할 것.
X110 Y100 위치로 이동하면서 새롭게 12mm를 압출할 것.

위의 두 코드를 실제 실행한다면, Absolute Extrusion 모드에서는 총 12mm 길이의 필라멘트를 압출한 셈이 되고, Relative Extrusion 모드라면 22mm 길이의 필라멘트를 압출한 셈이 됩니다. 동일한 코드이지만, Absoulte Extrusion 모드일 경우와 Relative Extrusion 모드일 경우, 해석이 완전히 다른 셈입니다. 

아래는 동일한 3D 모델(매우 잘 알려진 XYZ Cube ^^)을 Simplify3D Slicer에서 Absoulte E와 Relative E 모드로 각각 Slicing을 하고 Gcode로 저장한 후, Text 편집기를 통해 확인한 것입니다. 매우 긴 파일이지만, 동일한 Segment Sequence의 극히 일 부분을 발취한 것입니다.

비교 스샷1왼쪽) Absolute E 모드 , 오른쪽) Relative E 모드

위의 스샷에서 왼쪽이 Absolute E 이고, 오른쪽이 Relative E 입니다. 왼쪽 Segment Sequence를 보면, 0.009 -> 0.0309 -> 0.0708 ... 과 같이 E값이 점점 커지는 것을 볼 수 있으실 것입니다.  Absolute E 모드의 각 Segment에 정의된 E 값을 바로 직전 Segment E값과 비교 연산을 하면, 왼쪽의 Relative E 모드의 각 Segment의 E 값과 동일한 것을 확인하실 수 있습니다.  

당연히 같아야 겠지요.. 다르다면 완전 다르게 출력이 될 것이니 말입니다. ^^

어차피 Absolute E 모드로 만들어진 Gcode의 Segment Sequence는 컨트롤러의 펌웨어로 들어가면, 이전 E값과 현재의 E값을 연산하여 압출할 양을 계산해 낼 것이고, Relative E 모드로 만들어진 Gcode의 Segment Sequence는 컨트롤러 펌웨어에서 연산 없이 그대로 현재의 압출량으로 사용 하게 됩니다.  현재의 압출량은 이론상으로는 두 모드 공히 동일할 것입니다. 여기까지 보면, 일단 Relative E 모드로 만들어진 Gcode가 펌웨어 입장에서는 직전 정보를 기억하고 있을 필요가 없고, 이전 값과 비교 연산을 할 필요가 없다는 잇점이 있다는 것을 짐작할 수 있을 텐데요.. 

그렇다면...  빼기계산을 안한다는 것 이 외에 Relative E 모드가 무슨 잇점이 있다는 말인가 ??

Rounding Error

우선 3D 프린터의 컨트롤러(MCU)가 하는 가장 주요한 역활은 Stepper Motor를 구동시키기 위한 Step Pulse를 생성해 내는 것이라는 점을 이해할 필요가 있습니다. Stepper Motor는 Step이라는 단위로 회전을 하게 되는데, 회전을 하기 위해서는 Step pulse를 입력 받아야 합니다. 실제로는 MCU가 생성한 Step Pulse를 Stepper Motor가 직접 받는 것은 아니고, 중간에 Stepper Driver라는 녀석을 거치게 되죠.. Step pulse를 생성하는 것이 바로 3D프린터의 컨트롤러가 하는 역활이고, 더 엄밀히 말하면 컨트롤러에 내장된 소프트웨어인 펌웨어(Firmware)가 그 역활을 합니다. 

각 축을 담당하는 Stepper Motor와 마찬가지로 필라멘트를 압출하기 위해서는 압출기(Extruder)가 필요하고, 이 압출기에도 Stepper Motor가 달려 있습니다. 이 포스트에서 자세히 다루지는 않겠지만.. 가장 많이 사용하는 Marlin Firmware의 경우, Configuration.h 에 step/mm 라는 것을 정의하게 되어 있습니다

step/mm 즉, 1mm를 진행하기 위해 필요한 Step 수를 의미하는데, 대부분은 Micro Stepping을 사용하므로 여기서 말하는 Step은 Micro Step이 됩니다. (Micro Step에 대한 설명도 일단 생략)..  예를 들어, Extruder(압출기)의 Stepper Motor에 대한 step/mm가 418 이라면. 이는 1mm를 압출하는데, 418 Micro Step이 필요하다는 것을 의미합니다.  

따라서, G1 명령어에 포함된 E(압출량, mm) 값과 step/mm 값을 이용하여 연산을 하면, 해당 G1 명령을 통해 Extruder의 Stepper Motor에 얼마의 step pulse를 제공해야 하는 지가 결정되게 됩니다. 이전 값과의 연산결과 E값이 0.2mm 라면, 418 * 0.2 = 83.6 step pulse를 생성해야 하는 것이죠.  0.6 step 이라는 것은 없으므로.. 83 혹은 84 step pulse를 생성하게 될 것 입니다.

암튼, 정확하고 정밀하게 출력을 하기 위해서는 당연히 정확한 E값이 필요합니다. 헌데, Absolute E 모드를 사용할 경우에는 이 정확도가 떨어지는 치명적인 문제를 내포하고 있습니다.

이유는 엉뚱하게도 실수값(float)과 관련된 것입니다. 

마이크로프로세서는 실수값을 특정한 길이의 저장공간에 저장합니다. 예를 들어 하나의 실수값을 저장하기 위해 32bit 길이 만큼의 저장공간이 필요하다고 가정을 해 봅니다. 실수는 정수부와 소수부로 나눠져 있죠. 예를 들어 3.141592 라는 실수는 3이라는 정수부와 141592라는 소수부가 있습니다. 3이라는 정수부와 141592라는 소수부가 모두 32bit의 저장공간에 저장이 되어야 하는 것이고, 예를 들어 32비트 저장공간에 딱 저장할 수 있다고 가정을 합니다. 헌데, 만일 이 실수값의 정수부가 점점 커진다고 가정을 해 봅니다. 30.141592,  300.141592,  3000.141592... 이런식으로 말이죠..

3.141592를 겨우 저장할 수 있는 상태였는데, 이제 30.141592를 저장해야 한다면.. 저장을 할 수가 없게 됩니다.  따라서, 뒤의 소수부의 가장 작은 값을 적당히 반올림 처리하고, 대신 정수부의 정보를 저장하게 됩니다.  그래서 30.141592가 아닌 30.14159가 저장되게 되는 것이죠.. 같은 방식으로 300.141592는 300.1416이 3000.141592는 3000.142이 저장되게 됩니다. 이는 어디까지나 이해를 돕기 위한 예일 뿐 실제로 정확히 이렇게 저장된다는 것은 아닙니다. ^^  어쨋든 분명한 것은 하나의 실수를 저장하기 위한 저장공간은 고정되어 있고.. 값이 점점 커지면 커질 수록 소수파트의 정밀도가 줄어들게 된다는 점을 이해할 필요가 있습니다. 

여기까지 눈치가 빠른 분들은 이미 이해를 하셨겠지요.. ^^

Absolute E 모드는 E값이 0mm 인 시점을 출발해서 3D모델의 출력이 종료되는 시점까지의 모든 E값이 계속 누적되는 방식입니다. 즉, E값이 점점 커지게 되는 것이죠.. E값이 계속 커지면 현재의 E값도 그리고, 바로 직전의 E값도 모두 점점 정밀도가 떨아진 상태로 저장이 되게 되며.. 값이 커지면 커질수록 더욱 더 정밀도가 떨아지게 될 것입니다. 이렇게 소수의 작은 부분이 저장을 위해 잘려나감으로 써 생기는 오차를 Rounding Error라고 합니다. 

어느 시점에 바로 직전의 E값이 12456,121234 이였고, 현재 Segment의 E 값이 12456.13300 이였다면. 실제 펌웨어 상에는 rounding error로 이전 값은 12456.121, 현재 값은 12456.133이 저장되게 되면, 이 매우 큰 두 값을 연산한 결과도 역시 정확한 값이 아닐 것 입니다. 

즉, 정리하자면 Absoulte E 방식의 경우에는 "Rounding Error가 계속 누적되는 문제를 내포하고 있다" 고 할 수 있습니다

이 문제는 사실 이미 매우 잘 알려진 문제이고, 이를 Slicing S/W를 개발하는 개발자들도 알고 있기 때문에, E 값이 점점 커지는 것을 방지하는 방법을 사용합니다.  값이 커지지 않는다면 Rounding Error도 커지지 않을 테니 말이죠..

분석 스샷1

위의 스샷을 보면, Retraction 시점, 그리고 다시 Extract 되는 시점, 그리고 layer를 다시 그리는 시점에 "G92 E0" 라고 하는 Gcode를 사용하고 있는 것을 보실 수 있을 겁니다.

G92 E0라는 명령은 "현 시점에서 압출(Extrusion)값을 0으로 초기화 하라"는 명령어 입니다.

Extrusion을 0으로 초기화 했으니, 다음 Segment에서는 E값을 다시 매우 작은 값부터 다시 시작할 수 있습니다. 즉, 하나의 큰 이벤트가 종료되고 다음 이벤트가 시작되는 시점에 Extrusion의 값을 초기화 시키는 방법을 사용함으로써, E값이 무한정 커지는 것을 방지하고.. 이는 결국 rounding error를 줄이는 사이드 이펙트를 얻게 됩니다.  

반면, Relative E 모드는 현 Segment를 수행하는데 필요한 E 값을 정의하고 있으므로... 값 자체가 커질 이유가 없고, 값이 대부분 작기 때문에 매우 정밀한 소수값을 실수저장 공간에 모두 손실 없이 온전히 저장할 수 있습니다. 이는 결론적으로 매우 정밀한 step pulse를 생성할 수 있다는 의미가 되며, 보다 정밀한 압출을 수행할 수 있다는 의미가 된다고 할 수 있습니다. 

Absolute E 모드나 Relative E 모드나 표현의 차이가 있을 뿐 값 자체는 Ideal하게 동일하지만, 그 결과는 매우 다른 셈 입니다. 

매우 최근까지도 Absolute E 모드가 주로 사용되어 왔는데, 이유는 Slicer들이 지원을 하지 않았기 때문입니다. 하지만, 현재는 거의 모든 Slicer들이 Relative E 모드를 지원하고 있죠. 아래는 Relative E 모드 설정과 관련된 각 Slicer들의 설정화면 입니다.  각자 표현은 다르지만 모두 Relative Extrusion과 관련된 설정 옵션들 입니다. 

Cura Relative Extrusion 메뉴Cura의 경우에는 Special Modes 아래 Relative Extrusion 옵션이 숨어 있다.

slic3R PE relative E distance 메뉴Slic3r의 경우에는 Printer 설정아래 Advanced 항목에 있다.

S3D Relative Extrusion distances 메뉴Simplify3d의 경우는 G-Code 메뉴에 있다.

다만, 전통적으로 Absolute E 모드를 사용해 왔던 관습 때문에, 기본 설정은 Absolute E 모드로 되어 있습니다. 만일 지금까지 이러한 사실을 모르고 3D프린터를 사용하셨다면, Absolute E 모드로 사용 하고 있었다고 봐도 무관합니다. 

M82 / M83

앞서 설펴봤듯이 G1 코드 자체만으로는 이 Gcode가 Absolute E 모드로 생성된 것인지, Relative E 모드로 생성된 것인지를 식별할 방법은 없습니다. 단지 특정 모드로 생성되었다는 가정 하에서 E값에 대한 해석이 달라진다는 점만 우리는 위에서 확인을 했습니다. 

따라서, Slicer가 Gcode를 생성할 때, Absolute E 모드 인지 혹은 Relative E 모드인지를 Gcode 앞단에 표시해 줘야 하는데, 이 때 사용하는 GCode 명령어가 M82(Absolute E) 혹은 M83(Relative E) 입니다.

비교스샷2왼쪽) Relative E 모드, 오른쪽) Absolute E 모드

위의 스샷을 보면, 각 Gcode 파일 내에 M82, M83이 선언되어 있는 것을 확인하실 수 있습니다.

즉, 해당 Gcode가 컨트롤러의 펌웨어로 전달되면, 펌웨어는 이 명령어를 확인함으로써, 해당 Gcode가 Absolute E 모드로 만들어진 Gcode인지 혹은 Relative E 모드로 만들어진 GCode인지를 식별할 수 있는 것입니다. 이 코드는 Slicer의 Gcode 생성 모드를 설정하면 Gcode를 생성할 때 Slicer 소프트웨어가 자동으로 넣어 주는 것이므로, 사용자가 일부러 넣어줄 필요는 없습니다. 

자, 이제 정리를 해 보면, Absolute E 모드를 사용하면 Rounding Error라는 내제된 문제로 인해 보다 정확한 압출이 되지 않을 수 있기는 하지만, 이를 방지하기 위해 E값을 0로 reset하는 방법을 사용하고 있다고 했습니다. 결국 압출의 정확도만을 보면, Absolute E 모드를 Relative E 모드로 변경함으로써 얻을 수 있는 잇점은 그리 커 보이지 않습니다. 이미 이 문제에 충분히 대응하고 있다고 볼 수 있는 것이죠. 하지만, 좋은게 좋은 것... 과거에는 지원을 안해서 못 썼다고 하지만, 지금은 대부분 지원하는데, 굳이 사용하지 않을 이유 또한 없습니다. Relative E 모드를 사용하면 얻을 수 있는 정점을 정리하면 아래와 같습니다.

- 실수 저장, 실수 연산에 따른 runding error가 발생하지 않으므로 보다 정교한 step pulse를 생성할 수 있다.
- E값이 커지는 것을 방지하기 위한 G92 E0 코드가 불 필요하다.
- 펌웨어에서 이전 Extrusion 값을 저장/관리 할 필요가 없다.
- 펌웨어에서 Extrusion 연산에 대한 부담을 줄일 수 있다.
- Tool change 로직이 매우 심플해 질 수 있다.
- G1 코드에 대한 가독성이 높아지고, Slicing 버그를 찾는 것이 매우 용이해 진다.

주의 할 점

보통 Slicer의 Start / End Script 부분에 실제 출력에 앞서, Extruder의 노즐을 청소하기 위한 코드를 넣어 사용하는 경우가 있는데, 이 때 적용된 Code가 Absolute E에 대응하는 코드였다면 이를 Relative E에 대응 하는 코드로 바꿔줘야 합니다. 

만약 Retraction하는 부분이라면 -값으로 정의를 해 줘야 하며.. 나머지 Extract 부분은 각 segment에서 압출할 작은 양으로 다시 정의를 해 줘야 합니다.  End Script 도 마찬가지로 확인 후 고쳐 주셔야 하겠죠.  

Absolute E 모드로 정의된 Segment는 Relative E 모드에서 해석하면 엄청나게 많은 양의 필라멘트를 한 번에 압출하라는 명령어로 처리될 수 있다는 점...!!!  정말 주의해야 합니다. ^^

공유하기 링크
Comments